forked from rpms/glibc
import glibc-2.28-101.el8
This commit is contained in:
parent
9aaa9b05a8
commit
88b287be24
49
SOURCES/glibc-rh1361965.patch
Normal file
49
SOURCES/glibc-rh1361965.patch
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
Backport of this Fedora Rawhide commit but split out into a distinct
|
||||||
|
patch.
|
||||||
|
|
||||||
|
commit 72195d44855ab96875f117acb75c37f98dcb26a9
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Thu Jun 6 23:58:21 2019 -0400
|
||||||
|
|
||||||
|
locale: Fix C.UTF-8 ranges.
|
||||||
|
|
||||||
|
The ellipsis range support only allows <Uxxxx> or <Uxxxxxxxx> as
|
||||||
|
valid unicode code points, otherwise it treats it as a symbol and
|
||||||
|
since we don't define the symbol the entire range is unused.
|
||||||
|
|
||||||
|
diff --git a/localedata/locales/C b/localedata/locales/C
|
||||||
|
index b2c2d1dc417cde69..30d9563213b8cb0f 100644
|
||||||
|
--- a/localedata/locales/C
|
||||||
|
+++ b/localedata/locales/C
|
||||||
|
@@ -43,21 +43,21 @@ order_start forward
|
||||||
|
<U0000>
|
||||||
|
..
|
||||||
|
<UFFFF>
|
||||||
|
-<U10000>
|
||||||
|
+<U00010000>
|
||||||
|
..
|
||||||
|
-<U1FFFF>
|
||||||
|
-<U20000>
|
||||||
|
+<U0001FFFF>
|
||||||
|
+<U00020000>
|
||||||
|
..
|
||||||
|
-<U2FFFF>
|
||||||
|
-<UE0000>
|
||||||
|
+<U0002FFFF>
|
||||||
|
+<U000E0000>
|
||||||
|
..
|
||||||
|
-<UEFFFF>
|
||||||
|
-<UF0000>
|
||||||
|
+<U000EFFFF>
|
||||||
|
+<U000F0000>
|
||||||
|
..
|
||||||
|
-<UFFFFF>
|
||||||
|
-<U100000>
|
||||||
|
+<U000FFFFF>
|
||||||
|
+<U00100000>
|
||||||
|
..
|
||||||
|
-<U10FFFF>
|
||||||
|
+<U0010FFFF>
|
||||||
|
UNDEFINED
|
||||||
|
order_end
|
||||||
|
END LC_COLLATE
|
185
SOURCES/glibc-rh1410154-1.patch
Normal file
185
SOURCES/glibc-rh1410154-1.patch
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
commit 96cd0558bcd69481ccc42e1b392f0c0b36fce2b0
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Nov 28 19:59:45 2018 +0100
|
||||||
|
|
||||||
|
support: Add signal support to support_capture_subprocess_check
|
||||||
|
|
||||||
|
Signal zero does not terminate a process, so it is safe to use negative
|
||||||
|
values for signal numbers.
|
||||||
|
|
||||||
|
Adjust libio/tst-vtables-common.c to use this new functionality,
|
||||||
|
instead of determining the termination status for a signal indirectly.
|
||||||
|
|
||||||
|
diff --git a/libio/tst-vtables-common.c b/libio/tst-vtables-common.c
|
||||||
|
index 5e3101206919fa1b..85e246cd1131f8e8 100644
|
||||||
|
--- a/libio/tst-vtables-common.c
|
||||||
|
+++ b/libio/tst-vtables-common.c
|
||||||
|
@@ -380,21 +380,6 @@ without_compatibility_fflush (void *closure)
|
||||||
|
_exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Exit status after abnormal termination. */
|
||||||
|
-static int termination_status;
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-init_termination_status (void)
|
||||||
|
-{
|
||||||
|
- pid_t pid = xfork ();
|
||||||
|
- if (pid == 0)
|
||||||
|
- abort ();
|
||||||
|
- xwaitpid (pid, &termination_status, 0);
|
||||||
|
-
|
||||||
|
- TEST_VERIFY (WIFSIGNALED (termination_status));
|
||||||
|
- TEST_COMPARE (WTERMSIG (termination_status), SIGABRT);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void
|
||||||
|
check_for_termination (const char *name, void (*callback) (void *))
|
||||||
|
{
|
||||||
|
@@ -404,7 +389,7 @@ check_for_termination (const char *name, void (*callback) (void *))
|
||||||
|
shared->calls = 0;
|
||||||
|
struct support_capture_subprocess proc
|
||||||
|
= support_capture_subprocess (callback, NULL);
|
||||||
|
- support_capture_subprocess_check (&proc, name, termination_status,
|
||||||
|
+ support_capture_subprocess_check (&proc, name, -SIGABRT,
|
||||||
|
sc_allow_stderr);
|
||||||
|
const char *message
|
||||||
|
= "Fatal error: glibc detected an invalid stdio handle\n";
|
||||||
|
@@ -491,7 +476,6 @@ run_tests (bool initially_disabled)
|
||||||
|
|
||||||
|
shared = support_shared_allocate (sizeof (*shared));
|
||||||
|
shared->initially_disabled = initially_disabled;
|
||||||
|
- init_termination_status ();
|
||||||
|
|
||||||
|
if (initially_disabled)
|
||||||
|
{
|
||||||
|
diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
|
||||||
|
index d5eac84d09ae325f..2d2384e73df0d2d0 100644
|
||||||
|
--- a/support/capture_subprocess.h
|
||||||
|
+++ b/support/capture_subprocess.h
|
||||||
|
@@ -55,13 +55,16 @@ enum support_capture_allow
|
||||||
|
sc_allow_stderr = 0x04,
|
||||||
|
};
|
||||||
|
|
||||||
|
-/* Check that the subprocess exited with STATUS and that only the
|
||||||
|
- allowed outputs happened. ALLOWED is a combination of
|
||||||
|
- support_capture_allow flags. Report errors under the CONTEXT
|
||||||
|
- message. */
|
||||||
|
+/* Check that the subprocess exited and that only the allowed outputs
|
||||||
|
+ happened. If STATUS_OR_SIGNAL is nonnegative, it is the expected
|
||||||
|
+ (decoded) exit status of the process, as returned by WEXITSTATUS.
|
||||||
|
+ If STATUS_OR_SIGNAL is negative, -STATUS_OR_SIGNAL is the expected
|
||||||
|
+ termination signal, as returned by WTERMSIG. ALLOWED is a
|
||||||
|
+ combination of support_capture_allow flags. Report errors under
|
||||||
|
+ the CONTEXT message. */
|
||||||
|
void support_capture_subprocess_check (struct support_capture_subprocess *,
|
||||||
|
- const char *context, int status,
|
||||||
|
- int allowed)
|
||||||
|
+ const char *context,
|
||||||
|
+ int status_or_signal, int allowed)
|
||||||
|
__attribute__ ((nonnull (1, 2)));
|
||||||
|
|
||||||
|
#endif /* SUPPORT_CAPTURE_SUBPROCESS_H */
|
||||||
|
diff --git a/support/support_capture_subprocess_check.c b/support/support_capture_subprocess_check.c
|
||||||
|
index ff5ee89fb02599ae..8b4c352c96227b78 100644
|
||||||
|
--- a/support/support_capture_subprocess_check.c
|
||||||
|
+++ b/support/support_capture_subprocess_check.c
|
||||||
|
@@ -20,6 +20,7 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <support/capture_subprocess.h>
|
||||||
|
#include <support/check.h>
|
||||||
|
+#include <sys/wait.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_context (const char *context, bool *failed)
|
||||||
|
@@ -31,9 +32,22 @@ print_context (const char *context, bool *failed)
|
||||||
|
printf ("error: subprocess failed: %s\n", context);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+print_actual_status (struct support_capture_subprocess *proc)
|
||||||
|
+{
|
||||||
|
+ if (WIFEXITED (proc->status))
|
||||||
|
+ printf ("error: actual exit status: %d [0x%x]\n",
|
||||||
|
+ WEXITSTATUS (proc->status), proc->status);
|
||||||
|
+ else if (WIFSIGNALED (proc->status))
|
||||||
|
+ printf ("error: actual termination signal: %d [0x%x]\n",
|
||||||
|
+ WTERMSIG (proc->status), proc->status);
|
||||||
|
+ else
|
||||||
|
+ printf ("error: actual undecoded exit status: [0x%x]\n", proc->status);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
support_capture_subprocess_check (struct support_capture_subprocess *proc,
|
||||||
|
- const char *context, int status,
|
||||||
|
+ const char *context, int status_or_signal,
|
||||||
|
int allowed)
|
||||||
|
{
|
||||||
|
TEST_VERIFY ((allowed & sc_allow_none)
|
||||||
|
@@ -44,11 +58,28 @@ support_capture_subprocess_check (struct support_capture_subprocess *proc,
|
||||||
|
|| (allowed & sc_allow_stderr))));
|
||||||
|
|
||||||
|
bool failed = false;
|
||||||
|
- if (proc->status != status)
|
||||||
|
+ if (status_or_signal >= 0)
|
||||||
|
{
|
||||||
|
- print_context (context, &failed);
|
||||||
|
- printf ("error: expected exit status: %d\n", status);
|
||||||
|
- printf ("error: actual exit status: %d\n", proc->status);
|
||||||
|
+ /* Expect regular termination. */
|
||||||
|
+ if (!(WIFEXITED (proc->status)
|
||||||
|
+ && WEXITSTATUS (proc->status) == status_or_signal))
|
||||||
|
+ {
|
||||||
|
+ print_context (context, &failed);
|
||||||
|
+ printf ("error: expected exit status: %d\n", status_or_signal);
|
||||||
|
+ print_actual_status (proc);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* status_or_signal < 0. Expect termination by signal. */
|
||||||
|
+ if (!(WIFSIGNALED (proc->status)
|
||||||
|
+ && WTERMSIG (proc->status) == -status_or_signal))
|
||||||
|
+ {
|
||||||
|
+ print_context (context, &failed);
|
||||||
|
+ printf ("error: expected termination signal: %d\n",
|
||||||
|
+ -status_or_signal);
|
||||||
|
+ print_actual_status (proc);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
if (!(allowed & sc_allow_stdout) && proc->out.length != 0)
|
||||||
|
{
|
||||||
|
diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c
|
||||||
|
index 63b6699622f97fcc..99570879eedd65b1 100644
|
||||||
|
--- a/support/tst-support_capture_subprocess.c
|
||||||
|
+++ b/support/tst-support_capture_subprocess.c
|
||||||
|
@@ -285,15 +285,29 @@ do_multiple_tests (enum test_type type)
|
||||||
|
|
||||||
|
check_stream ("stdout", &result.out, test.out);
|
||||||
|
check_stream ("stderr", &result.err, test.err);
|
||||||
|
+
|
||||||
|
+ /* Allowed output for support_capture_subprocess_check. */
|
||||||
|
+ int check_allow = 0;
|
||||||
|
+ if (lengths[length_idx_stdout] > 0)
|
||||||
|
+ check_allow |= sc_allow_stdout;
|
||||||
|
+ if (lengths[length_idx_stderr] > 0)
|
||||||
|
+ check_allow |= sc_allow_stderr;
|
||||||
|
+ if (check_allow == 0)
|
||||||
|
+ check_allow = sc_allow_none;
|
||||||
|
+
|
||||||
|
if (test.signal != 0)
|
||||||
|
{
|
||||||
|
TEST_VERIFY (WIFSIGNALED (result.status));
|
||||||
|
TEST_VERIFY (WTERMSIG (result.status) == test.signal);
|
||||||
|
+ support_capture_subprocess_check (&result, "signal",
|
||||||
|
+ -SIGTERM, check_allow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TEST_VERIFY (WIFEXITED (result.status));
|
||||||
|
TEST_VERIFY (WEXITSTATUS (result.status) == test.status);
|
||||||
|
+ support_capture_subprocess_check (&result, "exit",
|
||||||
|
+ test.status, check_allow);
|
||||||
|
}
|
||||||
|
support_capture_subprocess_free (&result);
|
||||||
|
free (test.out);
|
42
SOURCES/glibc-rh1410154-10.patch
Normal file
42
SOURCES/glibc-rh1410154-10.patch
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
commit e37c2cf299b61ce18f62852f6c5624c27829b610
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Oct 31 18:48:43 2019 +0100
|
||||||
|
|
||||||
|
Move _dl_open_check to its original place in dl_open_worker
|
||||||
|
|
||||||
|
This reverts the non-test change from commit d0093c5cefb7f7a4143f
|
||||||
|
("Call _dl_open_check after relocation [BZ #24259]"), given that
|
||||||
|
the underlying bug has been fixed properly in commit 61b74477fa7f63
|
||||||
|
("Remove all loaded objects if dlopen fails, ignoring NODELETE
|
||||||
|
[BZ #20839]").
|
||||||
|
|
||||||
|
Tested on x86-64-linux-gnu, with and without --enable-cet.
|
||||||
|
|
||||||
|
Change-Id: I995a6cfb89f25d2b0cf5e606428c2a93eb48fc33
|
||||||
|
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index 25838b073ac1edaf..e13968d4d7c4c83f 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -619,6 +619,8 @@ dl_open_worker (void *a)
|
||||||
|
_dl_debug_state ();
|
||||||
|
LIBC_PROBE (map_complete, 3, args->nsid, r, new);
|
||||||
|
|
||||||
|
+ _dl_open_check (new);
|
||||||
|
+
|
||||||
|
/* Print scope information. */
|
||||||
|
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
|
||||||
|
_dl_show_scope (new, 0);
|
||||||
|
@@ -699,12 +701,6 @@ dl_open_worker (void *a)
|
||||||
|
_dl_relocate_object (l, l->l_scope, reloc_mode, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* NB: Workaround for [BZ #20839] which doesn't remove the NODELETE
|
||||||
|
- object when _dl_open_check throws an exception. Move it after
|
||||||
|
- relocation to avoid leaving the NODELETE object mapped without
|
||||||
|
- relocation. */
|
||||||
|
- _dl_open_check (new);
|
||||||
|
-
|
||||||
|
/* This only performs the memory allocations. The actual update of
|
||||||
|
the scopes happens below, after failure is impossible. */
|
||||||
|
resize_scopes (new);
|
27
SOURCES/glibc-rh1410154-11.patch
Normal file
27
SOURCES/glibc-rh1410154-11.patch
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
commit 61a7c9df71ee4e6f94b56c20f0d37c6e17d5f284
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon Dec 2 14:53:16 2019 +0100
|
||||||
|
|
||||||
|
elf/tst-dlopenfail: Disable --no-as-needed for tst-dlopenfailmod1.so
|
||||||
|
|
||||||
|
Otherwise, the shared object dependency which triggers the load
|
||||||
|
failure is dropped, invalidating the test.
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index bf7c41f38be42184..467e810e784bb96d 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -1543,8 +1543,11 @@ LDFLAGS-tst-finilazyfailmod.so = \
|
||||||
|
$(objpfx)tst-dlopenfail: $(libdl)
|
||||||
|
$(objpfx)tst-dlopenfail.out: \
|
||||||
|
$(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so
|
||||||
|
-# Order matters here. tst-dlopenfaillinkmod.so's soname ensures
|
||||||
|
-# a run-time loader failure.
|
||||||
|
+# Order matters here. tst-dlopenfaillinkmod.so's soname ensures a
|
||||||
|
+# run-time loader failure. --as-needed breaks this test because
|
||||||
|
+# nothing actually references tst-dlopenfailmod2.so (with its soname
|
||||||
|
+# tst-dlopenfail-missingmod.so).
|
||||||
|
+LDFLAGS-tst-dlopenfailmod1.so = -Wl,--no-as-needed
|
||||||
|
$(objpfx)tst-dlopenfailmod1.so: \
|
||||||
|
$(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so
|
||||||
|
LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so
|
1229
SOURCES/glibc-rh1410154-12.patch
Normal file
1229
SOURCES/glibc-rh1410154-12.patch
Normal file
File diff suppressed because it is too large
Load Diff
328
SOURCES/glibc-rh1410154-13.patch
Normal file
328
SOURCES/glibc-rh1410154-13.patch
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
commit f8ed116aa574435c6e28260f21963233682d3b57
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 13 10:18:46 2019 +0100
|
||||||
|
|
||||||
|
dlopen: Rework handling of pending NODELETE status
|
||||||
|
|
||||||
|
Commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23 ("Block signals during
|
||||||
|
the initial part of dlopen") was deemed necessary because of
|
||||||
|
read-modify-write operations like the one in add_dependency in
|
||||||
|
elf/dl-lookup.c. In the old code, we check for any kind of NODELETE
|
||||||
|
status and bail out:
|
||||||
|
|
||||||
|
/* Redo the NODELETE check, as when dl_load_lock wasn't held
|
||||||
|
yet this could have changed. */
|
||||||
|
if (map->l_nodelete != link_map_nodelete_inactive)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
And then set pending status (during relocation):
|
||||||
|
|
||||||
|
if (flags & DL_LOOKUP_FOR_RELOCATE)
|
||||||
|
map->l_nodelete = link_map_nodelete_pending;
|
||||||
|
else
|
||||||
|
map->l_nodelete = link_map_nodelete_active;
|
||||||
|
|
||||||
|
If a signal arrives during relocation and the signal handler, through
|
||||||
|
lazy binding, adds a global scope dependency on the same map, it will
|
||||||
|
set map->l_nodelete to link_map_nodelete_active. This will be
|
||||||
|
overwritten with link_map_nodelete_pending by the dlopen relocation
|
||||||
|
code.
|
||||||
|
|
||||||
|
To avoid such problems in relation to the l_nodelete member, this
|
||||||
|
commit introduces two flags for active NODELETE status (irrevocable)
|
||||||
|
and pending NODELETE status (revocable until activate_nodelete is
|
||||||
|
invoked). As a result, NODELETE processing in dlopen does not
|
||||||
|
introduce further reasons why lazy binding from signal handlers
|
||||||
|
is unsafe during dlopen, and a subsequent commit can remove signal
|
||||||
|
blocking from dlopen.
|
||||||
|
|
||||||
|
This does not address pre-existing issues (unrelated to the NODELETE
|
||||||
|
changes) which make lazy binding in a signal handler during dlopen
|
||||||
|
unsafe, such as the use of malloc in both cases.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||||
|
index 243a028c443173c1..fa7f3e8174576e46 100644
|
||||||
|
--- a/elf/dl-close.c
|
||||||
|
+++ b/elf/dl-close.c
|
||||||
|
@@ -197,7 +197,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
/* Check whether this object is still used. */
|
||||||
|
if (l->l_type == lt_loaded
|
||||||
|
&& l->l_direct_opencount == 0
|
||||||
|
- && l->l_nodelete != link_map_nodelete_active
|
||||||
|
+ && !l->l_nodelete_active
|
||||||
|
/* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why
|
||||||
|
acquire is sufficient and correct. */
|
||||||
|
&& atomic_load_acquire (&l->l_tls_dtor_count) == 0
|
||||||
|
@@ -279,8 +279,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
|
||||||
|
if (!used[i])
|
||||||
|
{
|
||||||
|
- assert (imap->l_type == lt_loaded
|
||||||
|
- && imap->l_nodelete != link_map_nodelete_active);
|
||||||
|
+ assert (imap->l_type == lt_loaded && !imap->l_nodelete_active);
|
||||||
|
|
||||||
|
/* Call its termination function. Do not do it for
|
||||||
|
half-cooked objects. Temporarily disable exception
|
||||||
|
@@ -820,7 +819,7 @@ _dl_close (void *_map)
|
||||||
|
before we took the lock. There is no way to detect this (see below)
|
||||||
|
so we proceed assuming this isn't the case. First see whether we
|
||||||
|
can remove the object at all. */
|
||||||
|
- if (__glibc_unlikely (map->l_nodelete == link_map_nodelete_active))
|
||||||
|
+ if (__glibc_unlikely (map->l_nodelete_active))
|
||||||
|
{
|
||||||
|
/* Nope. Do nothing. */
|
||||||
|
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||||
|
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
||||||
|
index 35a3f96a6296294a..01724a54f8840f9f 100644
|
||||||
|
--- a/elf/dl-lookup.c
|
||||||
|
+++ b/elf/dl-lookup.c
|
||||||
|
@@ -187,6 +187,28 @@ enter_unique_sym (struct unique_sym *table, size_t size,
|
||||||
|
table[idx].map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Mark MAP as NODELETE according to the lookup mode in FLAGS. During
|
||||||
|
+ initial relocation, NODELETE state is pending only. */
|
||||||
|
+static void
|
||||||
|
+mark_nodelete (struct link_map *map, int flags)
|
||||||
|
+{
|
||||||
|
+ if (flags & DL_LOOKUP_FOR_RELOCATE)
|
||||||
|
+ map->l_nodelete_pending = true;
|
||||||
|
+ else
|
||||||
|
+ map->l_nodelete_active = true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Return true if MAP is marked as NODELETE according to the lookup
|
||||||
|
+ mode in FLAGS> */
|
||||||
|
+static bool
|
||||||
|
+is_nodelete (struct link_map *map, int flags)
|
||||||
|
+{
|
||||||
|
+ /* Non-pending NODELETE always counts. Pending NODELETE only counts
|
||||||
|
+ during initial relocation processing. */
|
||||||
|
+ return map->l_nodelete_active
|
||||||
|
+ || ((flags & DL_LOOKUP_FOR_RELOCATE) && map->l_nodelete_pending);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Utility function for do_lookup_x. Lookup an STB_GNU_UNIQUE symbol
|
||||||
|
in the unique symbol table, creating a new entry if necessary.
|
||||||
|
Return the matching symbol in RESULT. */
|
||||||
|
@@ -311,8 +333,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
||||||
|
enter_unique_sym (entries, size,
|
||||||
|
new_hash, strtab + sym->st_name, sym, map);
|
||||||
|
|
||||||
|
- if (map->l_type == lt_loaded
|
||||||
|
- && map->l_nodelete == link_map_nodelete_inactive)
|
||||||
|
+ if (map->l_type == lt_loaded && !is_nodelete (map, flags))
|
||||||
|
{
|
||||||
|
/* Make sure we don't unload this object by
|
||||||
|
setting the appropriate flag. */
|
||||||
|
@@ -320,10 +341,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
||||||
|
_dl_debug_printf ("\
|
||||||
|
marking %s [%lu] as NODELETE due to unique symbol\n",
|
||||||
|
map->l_name, map->l_ns);
|
||||||
|
- if (flags & DL_LOOKUP_FOR_RELOCATE)
|
||||||
|
- map->l_nodelete = link_map_nodelete_pending;
|
||||||
|
- else
|
||||||
|
- map->l_nodelete = link_map_nodelete_active;
|
||||||
|
+ mark_nodelete (map, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++tab->n_elements;
|
||||||
|
@@ -586,7 +604,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
||||||
|
dependencies may pick an dependency which can be dlclose'd, but
|
||||||
|
such IFUNC resolvers are undefined anyway. */
|
||||||
|
assert (map->l_type == lt_loaded);
|
||||||
|
- if (map->l_nodelete != link_map_nodelete_inactive)
|
||||||
|
+ if (is_nodelete (map, flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct link_map_reldeps *l_reldeps
|
||||||
|
@@ -694,17 +712,16 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
||||||
|
|
||||||
|
/* Redo the NODELETE check, as when dl_load_lock wasn't held
|
||||||
|
yet this could have changed. */
|
||||||
|
- if (map->l_nodelete != link_map_nodelete_inactive)
|
||||||
|
+ if (is_nodelete (map, flags))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* If the object with the undefined reference cannot be removed ever
|
||||||
|
just make sure the same is true for the object which contains the
|
||||||
|
definition. */
|
||||||
|
- if (undef_map->l_type != lt_loaded
|
||||||
|
- || (undef_map->l_nodelete != link_map_nodelete_inactive))
|
||||||
|
+ if (undef_map->l_type != lt_loaded || is_nodelete (map, flags))
|
||||||
|
{
|
||||||
|
if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
||||||
|
- && map->l_nodelete == link_map_nodelete_inactive)
|
||||||
|
+ && !is_nodelete (map, flags))
|
||||||
|
{
|
||||||
|
if (undef_map->l_name[0] == '\0')
|
||||||
|
_dl_debug_printf ("\
|
||||||
|
@@ -716,11 +733,7 @@ marking %s [%lu] as NODELETE due to reference to %s [%lu]\n",
|
||||||
|
map->l_name, map->l_ns,
|
||||||
|
undef_map->l_name, undef_map->l_ns);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- if (flags & DL_LOOKUP_FOR_RELOCATE)
|
||||||
|
- map->l_nodelete = link_map_nodelete_pending;
|
||||||
|
- else
|
||||||
|
- map->l_nodelete = link_map_nodelete_active;
|
||||||
|
+ mark_nodelete (map, flags);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -746,17 +759,14 @@ marking %s [%lu] as NODELETE due to reference to %s [%lu]\n",
|
||||||
|
cannot be unloaded. This is semantically the correct
|
||||||
|
behavior. */
|
||||||
|
if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
||||||
|
- && map->l_nodelete == link_map_nodelete_inactive)
|
||||||
|
+ && !is_nodelete (map, flags))
|
||||||
|
_dl_debug_printf ("\
|
||||||
|
marking %s [%lu] as NODELETE due to memory allocation failure\n",
|
||||||
|
map->l_name, map->l_ns);
|
||||||
|
- if (flags & DL_LOOKUP_FOR_RELOCATE)
|
||||||
|
- /* In case of non-lazy binding, we could actually
|
||||||
|
- report the memory allocation error, but for now, we
|
||||||
|
- use the conservative approximation as well. */
|
||||||
|
- map->l_nodelete = link_map_nodelete_pending;
|
||||||
|
- else
|
||||||
|
- map->l_nodelete = link_map_nodelete_active;
|
||||||
|
+ /* In case of non-lazy binding, we could actually report
|
||||||
|
+ the memory allocation error, but for now, we use the
|
||||||
|
+ conservative approximation as well. */
|
||||||
|
+ mark_nodelete (map, flags);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index c7ed85b7ee99a296..a382bfae8aa3a2f8 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -440,13 +440,17 @@ activate_nodelete (struct link_map *new)
|
||||||
|
NODELETE status for objects outside the local scope. */
|
||||||
|
for (struct link_map *l = GL (dl_ns)[new->l_ns]._ns_loaded; l != NULL;
|
||||||
|
l = l->l_next)
|
||||||
|
- if (l->l_nodelete == link_map_nodelete_pending)
|
||||||
|
+ if (l->l_nodelete_pending)
|
||||||
|
{
|
||||||
|
if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES))
|
||||||
|
_dl_debug_printf ("activating NODELETE for %s [%lu]\n",
|
||||||
|
l->l_name, l->l_ns);
|
||||||
|
|
||||||
|
- l->l_nodelete = link_map_nodelete_active;
|
||||||
|
+ l->l_nodelete_active = true;
|
||||||
|
+
|
||||||
|
+ /* This is just a debugging aid, to indicate that
|
||||||
|
+ activate_nodelete has run for this map. */
|
||||||
|
+ l->l_nodelete_pending = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -549,10 +553,10 @@ dl_open_worker (void *a)
|
||||||
|
if (__glibc_unlikely (mode & RTLD_NODELETE))
|
||||||
|
{
|
||||||
|
if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)
|
||||||
|
- && new->l_nodelete == link_map_nodelete_inactive)
|
||||||
|
+ && !new->l_nodelete_active)
|
||||||
|
_dl_debug_printf ("marking %s [%lu] as NODELETE\n",
|
||||||
|
new->l_name, new->l_ns);
|
||||||
|
- new->l_nodelete = link_map_nodelete_active;
|
||||||
|
+ new->l_nodelete_active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finalize the addition to the global scope. */
|
||||||
|
@@ -568,7 +572,7 @@ dl_open_worker (void *a)
|
||||||
|
/* Schedule NODELETE marking for the directly loaded object if
|
||||||
|
requested. */
|
||||||
|
if (__glibc_unlikely (mode & RTLD_NODELETE))
|
||||||
|
- new->l_nodelete = link_map_nodelete_pending;
|
||||||
|
+ new->l_nodelete_pending = true;
|
||||||
|
|
||||||
|
/* Load that object's dependencies. */
|
||||||
|
_dl_map_object_deps (new, NULL, 0, 0,
|
||||||
|
@@ -680,7 +684,7 @@ dl_open_worker (void *a)
|
||||||
|
_dl_start_profile ();
|
||||||
|
|
||||||
|
/* Prevent unloading the object. */
|
||||||
|
- GL(dl_profile_map)->l_nodelete = link_map_nodelete_active;
|
||||||
|
+ GL(dl_profile_map)->l_nodelete_active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
@@ -879,9 +883,9 @@ no more namespaces available for dlmopen()"));
|
||||||
|
happens inside dl_open_worker. */
|
||||||
|
__libc_signal_restore_set (&args.original_signal_mask);
|
||||||
|
|
||||||
|
- /* All link_map_nodelete_pending objects should have been
|
||||||
|
- deleted at this point, which is why it is not necessary
|
||||||
|
- to reset the flag here. */
|
||||||
|
+ /* All l_nodelete_pending objects should have been deleted
|
||||||
|
+ at this point, which is why it is not necessary to reset
|
||||||
|
+ the flag here. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
__libc_signal_restore_set (&args.original_signal_mask);
|
||||||
|
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
|
||||||
|
index ea286abaea0128d1..78ba7e76db9706cc 100644
|
||||||
|
--- a/elf/get-dynamic-info.h
|
||||||
|
+++ b/elf/get-dynamic-info.h
|
||||||
|
@@ -164,7 +164,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||||
|
{
|
||||||
|
l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
|
||||||
|
if (l->l_flags_1 & DF_1_NODELETE)
|
||||||
|
- l->l_nodelete = link_map_nodelete_pending;
|
||||||
|
+ l->l_nodelete_pending = true;
|
||||||
|
|
||||||
|
/* Only DT_1_SUPPORTED_MASK bits are supported, and we would like
|
||||||
|
to assert this, but we can't. Users have been setting
|
||||||
|
diff --git a/include/link.h b/include/link.h
|
||||||
|
index a277b77cad6b52b1..e90fa79a0b332087 100644
|
||||||
|
--- a/include/link.h
|
||||||
|
+++ b/include/link.h
|
||||||
|
@@ -79,22 +79,6 @@ struct r_search_path_struct
|
||||||
|
int malloced;
|
||||||
|
};
|
||||||
|
|
||||||
|
-/* Type used by the l_nodelete member. */
|
||||||
|
-enum link_map_nodelete
|
||||||
|
-{
|
||||||
|
- /* This link map can be deallocated. */
|
||||||
|
- link_map_nodelete_inactive = 0, /* Zero-initialized in _dl_new_object. */
|
||||||
|
-
|
||||||
|
- /* This link map cannot be deallocated. */
|
||||||
|
- link_map_nodelete_active,
|
||||||
|
-
|
||||||
|
- /* This link map cannot be deallocated after dlopen has succeded.
|
||||||
|
- dlopen turns this into link_map_nodelete_active. dlclose treats
|
||||||
|
- this intermediate state as link_map_nodelete_active. */
|
||||||
|
- link_map_nodelete_pending,
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-
|
||||||
|
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
|
||||||
|
members form a chain of all the shared objects loaded at startup.
|
||||||
|
|
||||||
|
@@ -218,10 +202,17 @@ struct link_map
|
||||||
|
freed, ie. not allocated with
|
||||||
|
the dummy malloc in ld.so. */
|
||||||
|
|
||||||
|
- /* Actually of type enum link_map_nodelete. Separate byte due to
|
||||||
|
- a read in add_dependency in elf/dl-lookup.c outside the loader
|
||||||
|
- lock. Only valid for l_type == lt_loaded. */
|
||||||
|
- unsigned char l_nodelete;
|
||||||
|
+ /* NODELETE status of the map. Only valid for maps of type
|
||||||
|
+ lt_loaded. Lazy binding sets l_nodelete_active directly,
|
||||||
|
+ potentially from signal handlers. Initial loading of an
|
||||||
|
+ DF_1_NODELETE object set l_nodelete_pending. Relocation may
|
||||||
|
+ set l_nodelete_pending as well. l_nodelete_pending maps are
|
||||||
|
+ promoted to l_nodelete_active status in the final stages of
|
||||||
|
+ dlopen, prior to calling ELF constructors. dlclose only
|
||||||
|
+ refuses to unload l_nodelete_active maps, the pending status is
|
||||||
|
+ ignored. */
|
||||||
|
+ bool l_nodelete_active;
|
||||||
|
+ bool l_nodelete_pending;
|
||||||
|
|
||||||
|
#include <link_map.h>
|
||||||
|
|
134
SOURCES/glibc-rh1410154-14.patch
Normal file
134
SOURCES/glibc-rh1410154-14.patch
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
commit f7649d5780aa4682393b9daedd653e4d9c12784c
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 13 10:23:10 2019 +0100
|
||||||
|
|
||||||
|
dlopen: Do not block signals
|
||||||
|
|
||||||
|
Blocking signals causes issues with certain anti-malware solutions
|
||||||
|
which rely on an unblocked SIGSYS signal for system calls they
|
||||||
|
intercept.
|
||||||
|
|
||||||
|
This reverts commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23
|
||||||
|
("Block signals during the initial part of dlopen") and adds
|
||||||
|
comments related to async signal safety to active_nodelete and
|
||||||
|
its caller.
|
||||||
|
|
||||||
|
Note that this does not make lazy binding async-signal-safe with regards
|
||||||
|
to dlopen. It merely avoids introducing new async-signal-safety hazards
|
||||||
|
as part of the NODELETE changes.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index a382bfae8aa3a2f8..d834b89754d2b073 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -34,7 +34,6 @@
|
||||||
|
#include <atomic.h>
|
||||||
|
#include <libc-internal.h>
|
||||||
|
#include <array_length.h>
|
||||||
|
-#include <internal-signals.h>
|
||||||
|
|
||||||
|
#include <dl-dst.h>
|
||||||
|
#include <dl-prop.h>
|
||||||
|
@@ -53,10 +52,6 @@ struct dl_open_args
|
||||||
|
/* Namespace ID. */
|
||||||
|
Lmid_t nsid;
|
||||||
|
|
||||||
|
- /* Original signal mask. Used for unblocking signal handlers before
|
||||||
|
- running ELF constructors. */
|
||||||
|
- sigset_t original_signal_mask;
|
||||||
|
-
|
||||||
|
/* Original value of _ns_global_scope_pending_adds. Set by
|
||||||
|
dl_open_worker. Only valid if nsid is a real namespace
|
||||||
|
(non-negative). */
|
||||||
|
@@ -446,6 +441,9 @@ activate_nodelete (struct link_map *new)
|
||||||
|
_dl_debug_printf ("activating NODELETE for %s [%lu]\n",
|
||||||
|
l->l_name, l->l_ns);
|
||||||
|
|
||||||
|
+ /* The flag can already be true at this point, e.g. a signal
|
||||||
|
+ handler may have triggered lazy binding and set NODELETE
|
||||||
|
+ status immediately. */
|
||||||
|
l->l_nodelete_active = true;
|
||||||
|
|
||||||
|
/* This is just a debugging aid, to indicate that
|
||||||
|
@@ -520,16 +518,12 @@ dl_open_worker (void *a)
|
||||||
|
if (new == NULL)
|
||||||
|
{
|
||||||
|
assert (mode & RTLD_NOLOAD);
|
||||||
|
- __libc_signal_restore_set (&args->original_signal_mask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__glibc_unlikely (mode & __RTLD_SPROF))
|
||||||
|
- {
|
||||||
|
- /* This happens only if we load a DSO for 'sprof'. */
|
||||||
|
- __libc_signal_restore_set (&args->original_signal_mask);
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
+ /* This happens only if we load a DSO for 'sprof'. */
|
||||||
|
+ return;
|
||||||
|
|
||||||
|
/* This object is directly loaded. */
|
||||||
|
++new->l_direct_opencount;
|
||||||
|
@@ -565,7 +559,6 @@ dl_open_worker (void *a)
|
||||||
|
|
||||||
|
assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
|
||||||
|
|
||||||
|
- __libc_signal_restore_set (&args->original_signal_mask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -709,6 +702,12 @@ dl_open_worker (void *a)
|
||||||
|
All memory allocations for new objects must have happened
|
||||||
|
before. */
|
||||||
|
|
||||||
|
+ /* Finalize the NODELETE status first. This comes before
|
||||||
|
+ update_scopes, so that lazy binding will not see pending NODELETE
|
||||||
|
+ state for newly loaded objects. There is a compiler barrier in
|
||||||
|
+ update_scopes which ensures that the changes from
|
||||||
|
+ activate_nodelete are visible before new objects show up in the
|
||||||
|
+ local scope. */
|
||||||
|
activate_nodelete (new);
|
||||||
|
|
||||||
|
/* Second stage after resize_scopes: Actually perform the scope
|
||||||
|
@@ -742,10 +741,6 @@ dl_open_worker (void *a)
|
||||||
|
if (mode & RTLD_GLOBAL)
|
||||||
|
add_to_global_resize (new);
|
||||||
|
|
||||||
|
- /* Unblock signals. Data structures are now consistent, and
|
||||||
|
- application code may run. */
|
||||||
|
- __libc_signal_restore_set (&args->original_signal_mask);
|
||||||
|
-
|
||||||
|
/* Run the initializer functions of new objects. Temporarily
|
||||||
|
disable the exception handler, so that lazy binding failures are
|
||||||
|
fatal. */
|
||||||
|
@@ -835,10 +830,6 @@ no more namespaces available for dlmopen()"));
|
||||||
|
args.argv = argv;
|
||||||
|
args.env = env;
|
||||||
|
|
||||||
|
- /* Recursive lazy binding during manipulation of the dynamic loader
|
||||||
|
- structures may result in incorrect behavior. */
|
||||||
|
- __libc_signal_block_all (&args.original_signal_mask);
|
||||||
|
-
|
||||||
|
struct dl_exception exception;
|
||||||
|
int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
|
||||||
|
|
||||||
|
@@ -879,16 +870,10 @@ no more namespaces available for dlmopen()"));
|
||||||
|
|
||||||
|
_dl_close_worker (args.map, true);
|
||||||
|
|
||||||
|
- /* Restore the signal mask. In the success case, this
|
||||||
|
- happens inside dl_open_worker. */
|
||||||
|
- __libc_signal_restore_set (&args.original_signal_mask);
|
||||||
|
-
|
||||||
|
/* All l_nodelete_pending objects should have been deleted
|
||||||
|
at this point, which is why it is not necessary to reset
|
||||||
|
the flag here. */
|
||||||
|
}
|
||||||
|
- else
|
||||||
|
- __libc_signal_restore_set (&args.original_signal_mask);
|
||||||
|
|
||||||
|
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
|
||||||
|
|
27
SOURCES/glibc-rh1410154-15.patch
Normal file
27
SOURCES/glibc-rh1410154-15.patch
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
commit 5177d85b0c050a2333a0c4165c938dd422013d05
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Jan 16 06:45:36 2020 -0800
|
||||||
|
|
||||||
|
Clear GL(dl_initfirst) when freeing its link_map memory [BZ# 25396]
|
||||||
|
|
||||||
|
We should clear GL(dl_initfirst) when freeing its link_map memory.
|
||||||
|
|
||||||
|
Tested on Fedora 31/x86-64 with CET.
|
||||||
|
|
||||||
|
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||||
|
index fa7f3e8174576e46..a9ecdff62dba88fb 100644
|
||||||
|
--- a/elf/dl-close.c
|
||||||
|
+++ b/elf/dl-close.c
|
||||||
|
@@ -749,6 +749,10 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
if (imap->l_runpath_dirs.dirs != (void *) -1)
|
||||||
|
free (imap->l_runpath_dirs.dirs);
|
||||||
|
|
||||||
|
+ /* Clear GL(dl_initfirst) when freeing its link_map memory. */
|
||||||
|
+ if (imap == GL(dl_initfirst))
|
||||||
|
+ GL(dl_initfirst) = NULL;
|
||||||
|
+
|
||||||
|
free (imap);
|
||||||
|
}
|
||||||
|
}
|
143
SOURCES/glibc-rh1410154-16.patch
Normal file
143
SOURCES/glibc-rh1410154-16.patch
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
commit a332bd1518af518c984fad73eba6f46dc5b2b2d4
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Jan 16 16:53:58 2020 +0100
|
||||||
|
|
||||||
|
elf: Add elf/tst-dlopenfail-2 [BZ #25396]
|
||||||
|
|
||||||
|
Without CET, a jump into a newly loaded object through an overwritten
|
||||||
|
link map often does not crash, it just executes some random code.
|
||||||
|
CET detects this in some cases because the function pointer does not
|
||||||
|
point to the start of a function in the replacement shared object,
|
||||||
|
so there is no ENDBR instruction.
|
||||||
|
|
||||||
|
The new test uses a small shared object and the existing dangling
|
||||||
|
link map to trigger the bug.
|
||||||
|
|
||||||
|
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile
|
||||||
|
(Test backport differences.)
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 16a3e8dcda19b4ba..f1a16fe8ca594c57 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -192,7 +192,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
|
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
||||||
|
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
||||||
|
tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \
|
||||||
|
- tst-dlopenfail
|
||||||
|
+ tst-dlopenfail tst-dlopenfail-2
|
||||||
|
# reldep9
|
||||||
|
tests-internal += loadtest unload unload2 circleload1 \
|
||||||
|
neededtest neededtest2 neededtest3 neededtest4 \
|
||||||
|
@@ -301,7 +301,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||||
|
tst-sonamemove-linkmod1 \
|
||||||
|
tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
|
||||||
|
tst-initlazyfailmod tst-finilazyfailmod \
|
||||||
|
- tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2
|
||||||
|
+ tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
|
||||||
|
+ tst-dlopenfailmod3
|
||||||
|
|
||||||
|
ifeq (yes,$(have-mtls-dialect-gnu2))
|
||||||
|
tests += tst-gnu2-tls1
|
||||||
|
@@ -1569,6 +1570,10 @@ $(objpfx)tst-dlopenfailmod1.so: \
|
||||||
|
$(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so
|
||||||
|
LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so
|
||||||
|
$(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library)
|
||||||
|
+$(objpfx)tst-dlopenfail-2: $(libdl)
|
||||||
|
+$(objpfx)tst-dlopenfail.out: \
|
||||||
|
+ $(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so \
|
||||||
|
+ $(objpfx)tst-dlopenfailmod3.so
|
||||||
|
|
||||||
|
$(objpfx)tst-dlopen-nodelete-reloc: $(libdl)
|
||||||
|
$(objpfx)tst-dlopen-nodelete-reloc.out: \
|
||||||
|
diff --git a/elf/tst-dlopenfail-2.c b/elf/tst-dlopenfail-2.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..35bbde64abbb6603
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-dlopenfail-2.c
|
||||||
|
@@ -0,0 +1,59 @@
|
||||||
|
+/* Test unrelated dlopen after dlopen failure involving NODELETE.
|
||||||
|
+ Copyright (C) 2019-2020 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 <dlfcn.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <gnu/lib-names.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xdlfcn.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* This test uses libpthread as the canonical NODELETE module. If
|
||||||
|
+ libpthread is no longer NODELETE because it has been merged into
|
||||||
|
+ libc, the test needs to be updated. */
|
||||||
|
+ TEST_VERIFY (dlsym (NULL, "pthread_create") == NULL);
|
||||||
|
+
|
||||||
|
+ /* This is expected to fail because of the missing dependency. */
|
||||||
|
+ puts ("info: attempting to load tst-dlopenfailmod1.so");
|
||||||
|
+ TEST_VERIFY (dlopen ("tst-dlopenfailmod1.so", RTLD_LAZY) == NULL);
|
||||||
|
+ const char *message = dlerror ();
|
||||||
|
+ TEST_COMPARE_STRING (message,
|
||||||
|
+ "tst-dlopenfail-missingmod.so:"
|
||||||
|
+ " cannot open shared object file:"
|
||||||
|
+ " No such file or directory");
|
||||||
|
+
|
||||||
|
+ /* Open a small shared object. With a dangling GL (dl_initfirst)
|
||||||
|
+ pointer, this is likely to crash because there is no longer any
|
||||||
|
+ mapped text segment there (bug 25396). */
|
||||||
|
+
|
||||||
|
+ puts ("info: attempting to load tst-dlopenfailmod3.so");
|
||||||
|
+ xdlclose (xdlopen ("tst-dlopenfailmod3.so", RTLD_NOW));
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Do not perturb the dangling link map. With M_PERTURB, the link map
|
||||||
|
+ appears to have l_init_called set, so there are no constructor
|
||||||
|
+ calls and no crashes. */
|
||||||
|
+#define TEST_NO_MALLOPT
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-dlopenfailmod3.c b/elf/tst-dlopenfailmod3.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..636e971264292110
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-dlopenfailmod3.c
|
||||||
|
@@ -0,0 +1,17 @@
|
||||||
|
+/* Empty module for the tst-dlopenfail-2 test.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
33
SOURCES/glibc-rh1410154-2.patch
Normal file
33
SOURCES/glibc-rh1410154-2.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
commit ca136bb0a36d0a7056c926bfe5126873566efe40
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Oct 31 13:28:26 2019 +0100
|
||||||
|
|
||||||
|
Clarify purpose of assert in _dl_lookup_symbol_x
|
||||||
|
|
||||||
|
Only one of the currently defined flags is incompatible with versioned
|
||||||
|
symbol lookups, so it makes sense to check for that flag and not its
|
||||||
|
complement.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Reviewed-by: Gabriel F. T. Gomes <gabrielftg@linux.ibm.com>
|
||||||
|
Change-Id: I3384349cef90cfd91862ebc34a4053f0c0a99404
|
||||||
|
|
||||||
|
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
||||||
|
index 1d046caf017b582b..efbdb8deb3c0a9d4 100644
|
||||||
|
--- a/elf/dl-lookup.c
|
||||||
|
+++ b/elf/dl-lookup.c
|
||||||
|
@@ -792,11 +792,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
||||||
|
|
||||||
|
bump_num_relocations ();
|
||||||
|
|
||||||
|
- /* No other flag than DL_LOOKUP_ADD_DEPENDENCY or DL_LOOKUP_GSCOPE_LOCK
|
||||||
|
- is allowed if we look up a versioned symbol. */
|
||||||
|
- assert (version == NULL
|
||||||
|
- || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK))
|
||||||
|
- == 0);
|
||||||
|
+ /* DL_LOOKUP_RETURN_NEWEST does not make sense for versioned
|
||||||
|
+ lookups. */
|
||||||
|
+ assert (version == NULL || !(flags & DL_LOOKUP_RETURN_NEWEST));
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
if (__glibc_unlikely (skip_map != NULL))
|
54
SOURCES/glibc-rh1410154-3.patch
Normal file
54
SOURCES/glibc-rh1410154-3.patch
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
commit 2a764c6ee848dfe92cb2921ed3b14085f15d9e79
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Oct 31 13:23:06 2019 +0100
|
||||||
|
|
||||||
|
Enhance _dl_catch_exception to allow disabling exception handling
|
||||||
|
|
||||||
|
In some cases, it is necessary to introduce noexcept regions
|
||||||
|
where raised dynamic loader exceptions (e.g., from lazy binding)
|
||||||
|
are fatal, despite being nested in a code region with an active
|
||||||
|
exception handler. This change enhances _dl_catch_exception with
|
||||||
|
to provide such a capability. The existing function is reused,
|
||||||
|
so that it is not necessary to introduce yet another function with
|
||||||
|
a similar purpose.
|
||||||
|
|
||||||
|
Change-Id: Iec1bf642ff95a349fdde8040e9baf851ac7b8904
|
||||||
|
|
||||||
|
diff --git a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c
|
||||||
|
index d5f418ab1848f0c4..9cb002ccfed2c7b4 100644
|
||||||
|
--- a/elf/dl-error-skeleton.c
|
||||||
|
+++ b/elf/dl-error-skeleton.c
|
||||||
|
@@ -173,6 +173,18 @@ int
|
||||||
|
_dl_catch_exception (struct dl_exception *exception,
|
||||||
|
void (*operate) (void *), void *args)
|
||||||
|
{
|
||||||
|
+ /* If exception is NULL, temporarily disable exception handling.
|
||||||
|
+ Exceptions during operate (args) are fatal. */
|
||||||
|
+ if (exception == NULL)
|
||||||
|
+ {
|
||||||
|
+ struct catch *const old = catch_hook;
|
||||||
|
+ catch_hook = NULL;
|
||||||
|
+ operate (args);
|
||||||
|
+ /* If we get here, the operation was successful. */
|
||||||
|
+ catch_hook = old;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* We need not handle `receiver' since setting a `catch' is handled
|
||||||
|
before it. */
|
||||||
|
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index 95dc87519b80e0ec..cc2484033fe0d902 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -852,7 +852,9 @@ libc_hidden_proto (_dl_catch_error)
|
||||||
|
|
||||||
|
/* Call OPERATE (ARGS). If no error occurs, set *EXCEPTION to zero.
|
||||||
|
Otherwise, store a copy of the raised exception in *EXCEPTION,
|
||||||
|
- which has to be freed by _dl_exception_free. */
|
||||||
|
+ which has to be freed by _dl_exception_free. As a special case, if
|
||||||
|
+ EXCEPTION is null, call OPERATE (ARGS) with exception handling
|
||||||
|
+ disabled (so that exceptions are fatal). */
|
||||||
|
int _dl_catch_exception (struct dl_exception *exception,
|
||||||
|
void (*operate) (void *), void *args);
|
||||||
|
libc_hidden_proto (_dl_catch_exception)
|
42
SOURCES/glibc-rh1410154-4.patch
Normal file
42
SOURCES/glibc-rh1410154-4.patch
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
commit fcb04b9aed26a737159ef7be9c5a6ad0994437dc
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Oct 31 13:28:49 2019 +0100
|
||||||
|
|
||||||
|
Introduce DL_LOOKUP_FOR_RELOCATE flag for _dl_lookup_symbol_x
|
||||||
|
|
||||||
|
This will allow changes in dependency processing during non-lazy
|
||||||
|
binding, for more precise processing of NODELETE objects: During
|
||||||
|
initial relocation in dlopen, the fate of NODELETE objects is still
|
||||||
|
unclear, so objects which are depended upon by NODELETE objects
|
||||||
|
cannot immediately be marked as NODELETE.
|
||||||
|
|
||||||
|
Change-Id: Ic7b94a3f7c4719a00ca8e6018088567824da0658
|
||||||
|
|
||||||
|
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
|
||||||
|
index 053916eeae50467c..afeace4d3e49180c 100644
|
||||||
|
--- a/elf/dl-reloc.c
|
||||||
|
+++ b/elf/dl-reloc.c
|
||||||
|
@@ -248,7 +248,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||||
|
v = (version); \
|
||||||
|
_lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
|
||||||
|
scope, v, _tc, \
|
||||||
|
- DL_LOOKUP_ADD_DEPENDENCY, NULL); \
|
||||||
|
+ DL_LOOKUP_ADD_DEPENDENCY \
|
||||||
|
+ | DL_LOOKUP_FOR_RELOCATE, NULL); \
|
||||||
|
l->l_lookup_cache.ret = (*ref); \
|
||||||
|
l->l_lookup_cache.value = _lr; })) \
|
||||||
|
: l)
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index cc2484033fe0d902..6c5298a80bff8e96 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -908,6 +908,9 @@ enum
|
||||||
|
DL_LOOKUP_RETURN_NEWEST = 2,
|
||||||
|
/* Set if dl_lookup* called with GSCOPE lock held. */
|
||||||
|
DL_LOOKUP_GSCOPE_LOCK = 4,
|
||||||
|
+ /* Set if dl_lookup is called for non-lazy relocation processing
|
||||||
|
+ from _dl_relocate_object in elf/dl-reloc.c. */
|
||||||
|
+ DL_LOOKUP_FOR_RELOCATE = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Lookup versioned symbol. */
|
343
SOURCES/glibc-rh1410154-5.patch
Normal file
343
SOURCES/glibc-rh1410154-5.patch
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
commit 79e0cd7b3c997e211fad44a81fd839dc5b2546e8
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Nov 27 16:20:47 2019 +0100
|
||||||
|
|
||||||
|
Lazy binding failures during dlopen/dlclose must be fatal [BZ #24304]
|
||||||
|
|
||||||
|
If a lazy binding failure happens during the execution of an ELF
|
||||||
|
constructor or destructor, the dynamic loader catches the error
|
||||||
|
and reports it using the dlerror mechanism. This is undesirable
|
||||||
|
because there could be other constructors and destructors that
|
||||||
|
need processing (which are skipped), and the process is in an
|
||||||
|
inconsistent state at this point. Therefore, we have to issue
|
||||||
|
a fatal dynamic loader error error and terminate the process.
|
||||||
|
|
||||||
|
Note that the _dl_catch_exception in _dl_open is just an inner catch,
|
||||||
|
to roll back some state locally. If called from dlopen, there is
|
||||||
|
still an outer catch, which is why calling _dl_init via call_dl_init
|
||||||
|
and a no-exception is required and cannot be avoiding by moving the
|
||||||
|
_dl_init call directly into _dl_open.
|
||||||
|
|
||||||
|
_dl_fini does not need changes because it does not install an error
|
||||||
|
handler, so errors are already fatal there.
|
||||||
|
|
||||||
|
Change-Id: I6b1addfe2e30f50a1781595f046f44173db9491a
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile
|
||||||
|
(Usual conflicts due to test backport differences.)
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 74a240b3a68ff5e2..b752f6366400d221 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -191,7 +191,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
|
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
|
||||||
|
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
||||||
|
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
||||||
|
- tst-sonamemove-link tst-sonamemove-dlopen
|
||||||
|
+ tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail
|
||||||
|
# reldep9
|
||||||
|
tests-internal += loadtest unload unload2 circleload1 \
|
||||||
|
neededtest neededtest2 neededtest3 neededtest4 \
|
||||||
|
@@ -281,7 +281,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||||
|
tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \
|
||||||
|
tst-absolute-zero-lib tst-big-note-lib \
|
||||||
|
tst-sonamemove-linkmod1 \
|
||||||
|
- tst-sonamemove-runmod1 tst-sonamemove-runmod2
|
||||||
|
+ tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
|
||||||
|
+ tst-initlazyfailmod tst-finilazyfailmod
|
||||||
|
|
||||||
|
ifeq (yes,$(have-mtls-dialect-gnu2))
|
||||||
|
tests += tst-gnu2-tls1
|
||||||
|
@@ -1526,3 +1527,13 @@ tst-libc_dlvsym-static-ENV = \
|
||||||
|
$(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so
|
||||||
|
|
||||||
|
$(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so
|
||||||
|
+
|
||||||
|
+$(objpfx)tst-initfinilazyfail: $(libdl)
|
||||||
|
+$(objpfx)tst-initfinilazyfail.out: \
|
||||||
|
+ $(objpfx)tst-initlazyfailmod.so $(objpfx)tst-finilazyfailmod.so
|
||||||
|
+# Override -z defs, so that we can reference an undefined symbol.
|
||||||
|
+# Force lazy binding for the same reason.
|
||||||
|
+LDFLAGS-tst-initlazyfailmod.so = \
|
||||||
|
+ -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
|
||||||
|
+LDFLAGS-tst-finilazyfailmod.so = \
|
||||||
|
+ -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
|
||||||
|
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||||
|
index ecd6729704ea3294..88aeea25839a34e0 100644
|
||||||
|
--- a/elf/dl-close.c
|
||||||
|
+++ b/elf/dl-close.c
|
||||||
|
@@ -106,6 +106,30 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Invoke dstructors for CLOSURE (a struct link_map *). Called with
|
||||||
|
+ exception handling temporarily disabled, to make errors fatal. */
|
||||||
|
+static void
|
||||||
|
+call_destructors (void *closure)
|
||||||
|
+{
|
||||||
|
+ struct link_map *map = closure;
|
||||||
|
+
|
||||||
|
+ if (map->l_info[DT_FINI_ARRAY] != NULL)
|
||||||
|
+ {
|
||||||
|
+ ElfW(Addr) *array =
|
||||||
|
+ (ElfW(Addr) *) (map->l_addr
|
||||||
|
+ + map->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
|
||||||
|
+ unsigned int sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
|
||||||
|
+ / sizeof (ElfW(Addr)));
|
||||||
|
+
|
||||||
|
+ while (sz-- > 0)
|
||||||
|
+ ((fini_t) array[sz]) ();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Next try the old-style destructor. */
|
||||||
|
+ if (map->l_info[DT_FINI] != NULL)
|
||||||
|
+ DL_CALL_DT_FINI (map, ((void *) map->l_addr
|
||||||
|
+ + map->l_info[DT_FINI]->d_un.d_ptr));
|
||||||
|
+}
|
||||||
|
|
||||||
|
void
|
||||||
|
_dl_close_worker (struct link_map *map, bool force)
|
||||||
|
@@ -267,7 +291,8 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
&& (imap->l_flags_1 & DF_1_NODELETE) == 0);
|
||||||
|
|
||||||
|
/* Call its termination function. Do not do it for
|
||||||
|
- half-cooked objects. */
|
||||||
|
+ half-cooked objects. Temporarily disable exception
|
||||||
|
+ handling, so that errors are fatal. */
|
||||||
|
if (imap->l_init_called)
|
||||||
|
{
|
||||||
|
/* When debugging print a message first. */
|
||||||
|
@@ -276,22 +301,9 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
_dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
|
||||||
|
imap->l_name, nsid);
|
||||||
|
|
||||||
|
- if (imap->l_info[DT_FINI_ARRAY] != NULL)
|
||||||
|
- {
|
||||||
|
- ElfW(Addr) *array =
|
||||||
|
- (ElfW(Addr) *) (imap->l_addr
|
||||||
|
- + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
|
||||||
|
- unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
|
||||||
|
- / sizeof (ElfW(Addr)));
|
||||||
|
-
|
||||||
|
- while (sz-- > 0)
|
||||||
|
- ((fini_t) array[sz]) ();
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* Next try the old-style destructor. */
|
||||||
|
- if (imap->l_info[DT_FINI] != NULL)
|
||||||
|
- DL_CALL_DT_FINI (imap, ((void *) imap->l_addr
|
||||||
|
- + imap->l_info[DT_FINI]->d_un.d_ptr));
|
||||||
|
+ if (imap->l_info[DT_FINI_ARRAY] != NULL
|
||||||
|
+ || imap->l_info[DT_FINI] != NULL)
|
||||||
|
+ _dl_catch_exception (NULL, call_destructors, imap);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SHARED
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index 518a6cad699ec6d0..c9c0254ee74c4f4b 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -177,6 +177,23 @@ _dl_find_dso_for_object (const ElfW(Addr) addr)
|
||||||
|
}
|
||||||
|
rtld_hidden_def (_dl_find_dso_for_object);
|
||||||
|
|
||||||
|
+/* struct dl_init_args and call_dl_init are used to call _dl_init with
|
||||||
|
+ exception handling disabled. */
|
||||||
|
+struct dl_init_args
|
||||||
|
+{
|
||||||
|
+ struct link_map *new;
|
||||||
|
+ int argc;
|
||||||
|
+ char **argv;
|
||||||
|
+ char **env;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+call_dl_init (void *closure)
|
||||||
|
+{
|
||||||
|
+ struct dl_init_args *args = closure;
|
||||||
|
+ _dl_init (args->new, args->argc, args->argv, args->env);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
dl_open_worker (void *a)
|
||||||
|
{
|
||||||
|
@@ -506,8 +523,19 @@ TLS generation counter wrapped! Please report this."));
|
||||||
|
DL_STATIC_INIT (new);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- /* Run the initializer functions of new objects. */
|
||||||
|
- _dl_init (new, args->argc, args->argv, args->env);
|
||||||
|
+ /* Run the initializer functions of new objects. Temporarily
|
||||||
|
+ disable the exception handler, so that lazy binding failures are
|
||||||
|
+ fatal. */
|
||||||
|
+ {
|
||||||
|
+ struct dl_init_args init_args =
|
||||||
|
+ {
|
||||||
|
+ .new = new,
|
||||||
|
+ .argc = args->argc,
|
||||||
|
+ .argv = args->argv,
|
||||||
|
+ .env = args->env
|
||||||
|
+ };
|
||||||
|
+ _dl_catch_exception (NULL, call_dl_init, &init_args);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Now we can make the new map available in the global scope. */
|
||||||
|
if (mode & RTLD_GLOBAL)
|
||||||
|
diff --git a/elf/tst-finilazyfailmod.c b/elf/tst-finilazyfailmod.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..2670bd1a9400d0ef
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-finilazyfailmod.c
|
||||||
|
@@ -0,0 +1,27 @@
|
||||||
|
+/* Helper module for tst-initfinilazyfail: lazy binding failure in destructor.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+/* An undefined function. Calling it will cause a lazy binding
|
||||||
|
+ failure. */
|
||||||
|
+void undefined_function (void);
|
||||||
|
+
|
||||||
|
+static void __attribute__ ((destructor))
|
||||||
|
+fini (void)
|
||||||
|
+{
|
||||||
|
+ undefined_function ();
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-initfinilazyfail.c b/elf/tst-initfinilazyfail.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..9b4a3d0c0ffbb7c6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-initfinilazyfail.c
|
||||||
|
@@ -0,0 +1,84 @@
|
||||||
|
+/* Test that lazy binding failures in constructors and destructors are fatal.
|
||||||
|
+ Copyright (C) 2019 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 <dlfcn.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/capture_subprocess.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xdlfcn.h>
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+test_constructor (void *closure)
|
||||||
|
+{
|
||||||
|
+ void *handle = dlopen ("tst-initlazyfailmod.so", RTLD_LAZY);
|
||||||
|
+ if (handle == NULL)
|
||||||
|
+ FAIL_EXIT (2, "dlopen did not terminate the process: %s", dlerror ());
|
||||||
|
+ else
|
||||||
|
+ FAIL_EXIT (2, "dlopen did not terminate the process (%p)", handle);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+test_destructor (void *closure)
|
||||||
|
+{
|
||||||
|
+ void *handle = xdlopen ("tst-finilazyfailmod.so", RTLD_LAZY);
|
||||||
|
+ int ret = dlclose (handle);
|
||||||
|
+ const char *message = dlerror ();
|
||||||
|
+ if (message != NULL)
|
||||||
|
+ FAIL_EXIT (2, "dlclose did not terminate the process: %d, %s",
|
||||||
|
+ ret, message);
|
||||||
|
+ else
|
||||||
|
+ FAIL_EXIT (2, "dlopen did not terminate the process: %d", ret);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ {
|
||||||
|
+ struct support_capture_subprocess proc
|
||||||
|
+ = support_capture_subprocess (test_constructor, NULL);
|
||||||
|
+ support_capture_subprocess_check (&proc, "constructor", 127,
|
||||||
|
+ sc_allow_stderr);
|
||||||
|
+ printf ("info: constructor failure output: [[%s]]\n", proc.err.buffer);
|
||||||
|
+ TEST_VERIFY (strstr (proc.err.buffer,
|
||||||
|
+ "tst-initfinilazyfail: symbol lookup error: ")
|
||||||
|
+ != NULL);
|
||||||
|
+ TEST_VERIFY (strstr (proc.err.buffer,
|
||||||
|
+ "tst-initlazyfailmod.so: undefined symbol:"
|
||||||
|
+ " undefined_function\n") != NULL);
|
||||||
|
+ support_capture_subprocess_free (&proc);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ {
|
||||||
|
+ struct support_capture_subprocess proc
|
||||||
|
+ = support_capture_subprocess (test_destructor, NULL);
|
||||||
|
+ support_capture_subprocess_check (&proc, "destructor", 127,
|
||||||
|
+ sc_allow_stderr);
|
||||||
|
+ printf ("info: destructor failure output: [[%s]]\n", proc.err.buffer);
|
||||||
|
+ TEST_VERIFY (strstr (proc.err.buffer,
|
||||||
|
+ "tst-initfinilazyfail: symbol lookup error: ")
|
||||||
|
+ != NULL);
|
||||||
|
+ TEST_VERIFY (strstr (proc.err.buffer,
|
||||||
|
+ "tst-finilazyfailmod.so: undefined symbol:"
|
||||||
|
+ " undefined_function\n") != NULL);
|
||||||
|
+ support_capture_subprocess_free (&proc);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-initlazyfailmod.c b/elf/tst-initlazyfailmod.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..36348b58d634d2bb
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-initlazyfailmod.c
|
||||||
|
@@ -0,0 +1,27 @@
|
||||||
|
+/* Helper module for tst-initfinilazyfail: lazy binding failure in constructor.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+/* An undefined function. Calling it will cause a lazy binding
|
||||||
|
+ failure. */
|
||||||
|
+void undefined_function (void);
|
||||||
|
+
|
||||||
|
+static void __attribute__ ((constructor))
|
||||||
|
+init (void)
|
||||||
|
+{
|
||||||
|
+ undefined_function ();
|
||||||
|
+}
|
308
SOURCES/glibc-rh1410154-6.patch
Normal file
308
SOURCES/glibc-rh1410154-6.patch
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
commit 440b7f8653e4ed8f6e1425145208050b795e9a6c
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Oct 31 18:25:39 2019 +0100
|
||||||
|
|
||||||
|
Avoid late failure in dlopen in global scope update [BZ #25112]
|
||||||
|
|
||||||
|
The call to add_to_global in dl_open_worker happens after running ELF
|
||||||
|
constructors for new objects. At this point, proper recovery from
|
||||||
|
malloc failure would be quite complicated: We would have to run the
|
||||||
|
ELF destructors and close all opened objects, something that we
|
||||||
|
currently do not do.
|
||||||
|
|
||||||
|
Instead, this change splits add_to_global into two phases,
|
||||||
|
add_to_global_resize (which can raise an exception, called before ELF
|
||||||
|
constructors run), and add_to_global_update (which cannot, called
|
||||||
|
after ELF constructors). A complication arises due to recursive
|
||||||
|
dlopen: After the inner dlopen consumes some space, the pre-allocation
|
||||||
|
in the outer dlopen may no longer be sufficient. A new member in the
|
||||||
|
namespace structure, _ns_global_scope_pending_adds keeps track of the
|
||||||
|
maximum number of objects that need to be added to the global scope.
|
||||||
|
This enables the inner add_to_global_resize call to take into account
|
||||||
|
the needs of an outer dlopen.
|
||||||
|
|
||||||
|
Most code in the dynamic linker assumes that the number of global
|
||||||
|
scope entries fits into an unsigned int (matching the r_nlist member
|
||||||
|
of struct r_scop_elem). Therefore, change the type of
|
||||||
|
_ns_global_scope_alloc to unsigned int (from size_t), and add overflow
|
||||||
|
checks.
|
||||||
|
|
||||||
|
Change-Id: Ie08e2f318510d5a6a4bcb1c315f46791b5b77524
|
||||||
|
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index c9c0254ee74c4f4b..85db4f0ecb5f29ce 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -50,22 +50,38 @@ struct dl_open_args
|
||||||
|
struct link_map *map;
|
||||||
|
/* Namespace ID. */
|
||||||
|
Lmid_t nsid;
|
||||||
|
+
|
||||||
|
+ /* Original value of _ns_global_scope_pending_adds. Set by
|
||||||
|
+ dl_open_worker. Only valid if nsid is a real namespace
|
||||||
|
+ (non-negative). */
|
||||||
|
+ unsigned int original_global_scope_pending_adds;
|
||||||
|
+
|
||||||
|
/* Original parameters to the program and the current environment. */
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
char **env;
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* Called in case the global scope cannot be extended. */
|
||||||
|
+static void __attribute__ ((noreturn))
|
||||||
|
+add_to_global_resize_failure (struct link_map *new)
|
||||||
|
+{
|
||||||
|
+ _dl_signal_error (ENOMEM, new->l_libname->name, NULL,
|
||||||
|
+ N_ ("cannot extend global scope"));
|
||||||
|
+}
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-add_to_global (struct link_map *new)
|
||||||
|
+/* Grow the global scope array for the namespace, so that all the new
|
||||||
|
+ global objects can be added later in add_to_global_update, without
|
||||||
|
+ risk of memory allocation failure. add_to_global_resize raises
|
||||||
|
+ exceptions for memory allocation errors. */
|
||||||
|
+static void
|
||||||
|
+add_to_global_resize (struct link_map *new)
|
||||||
|
{
|
||||||
|
- struct link_map **new_global;
|
||||||
|
- unsigned int to_add = 0;
|
||||||
|
- unsigned int cnt;
|
||||||
|
+ struct link_namespaces *ns = &GL (dl_ns)[new->l_ns];
|
||||||
|
|
||||||
|
/* Count the objects we have to put in the global scope. */
|
||||||
|
- for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
||||||
|
+ unsigned int to_add = 0;
|
||||||
|
+ for (unsigned int cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
||||||
|
if (new->l_searchlist.r_list[cnt]->l_global == 0)
|
||||||
|
++to_add;
|
||||||
|
|
||||||
|
@@ -83,47 +99,51 @@ add_to_global (struct link_map *new)
|
||||||
|
in an realloc() call. Therefore we allocate a completely new
|
||||||
|
array the first time we have to add something to the locale scope. */
|
||||||
|
|
||||||
|
- struct link_namespaces *ns = &GL(dl_ns)[new->l_ns];
|
||||||
|
+ if (__builtin_add_overflow (ns->_ns_global_scope_pending_adds, to_add,
|
||||||
|
+ &ns->_ns_global_scope_pending_adds))
|
||||||
|
+ add_to_global_resize_failure (new);
|
||||||
|
+
|
||||||
|
+ unsigned int new_size = 0; /* 0 means no new allocation. */
|
||||||
|
+ void *old_global = NULL; /* Old allocation if free-able. */
|
||||||
|
+
|
||||||
|
+ /* Minimum required element count for resizing. Adjusted below for
|
||||||
|
+ an exponential resizing policy. */
|
||||||
|
+ size_t required_new_size;
|
||||||
|
+ if (__builtin_add_overflow (ns->_ns_main_searchlist->r_nlist,
|
||||||
|
+ ns->_ns_global_scope_pending_adds,
|
||||||
|
+ &required_new_size))
|
||||||
|
+ add_to_global_resize_failure (new);
|
||||||
|
+
|
||||||
|
if (ns->_ns_global_scope_alloc == 0)
|
||||||
|
{
|
||||||
|
- /* This is the first dynamic object given global scope. */
|
||||||
|
- ns->_ns_global_scope_alloc
|
||||||
|
- = ns->_ns_main_searchlist->r_nlist + to_add + 8;
|
||||||
|
- new_global = (struct link_map **)
|
||||||
|
- malloc (ns->_ns_global_scope_alloc * sizeof (struct link_map *));
|
||||||
|
- if (new_global == NULL)
|
||||||
|
- {
|
||||||
|
- ns->_ns_global_scope_alloc = 0;
|
||||||
|
- nomem:
|
||||||
|
- _dl_signal_error (ENOMEM, new->l_libname->name, NULL,
|
||||||
|
- N_("cannot extend global scope"));
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
+ if (__builtin_add_overflow (required_new_size, 8, &new_size))
|
||||||
|
+ add_to_global_resize_failure (new);
|
||||||
|
+ }
|
||||||
|
+ else if (required_new_size > ns->_ns_global_scope_alloc)
|
||||||
|
+ {
|
||||||
|
+ if (__builtin_mul_overflow (required_new_size, 2, &new_size))
|
||||||
|
+ add_to_global_resize_failure (new);
|
||||||
|
|
||||||
|
- /* Copy over the old entries. */
|
||||||
|
- ns->_ns_main_searchlist->r_list
|
||||||
|
- = memcpy (new_global, ns->_ns_main_searchlist->r_list,
|
||||||
|
- (ns->_ns_main_searchlist->r_nlist
|
||||||
|
- * sizeof (struct link_map *)));
|
||||||
|
+ /* The old array was allocated with our malloc, not the minimal
|
||||||
|
+ malloc. */
|
||||||
|
+ old_global = ns->_ns_main_searchlist->r_list;
|
||||||
|
}
|
||||||
|
- else if (ns->_ns_main_searchlist->r_nlist + to_add
|
||||||
|
- > ns->_ns_global_scope_alloc)
|
||||||
|
+
|
||||||
|
+ if (new_size > 0)
|
||||||
|
{
|
||||||
|
- /* We have to extend the existing array of link maps in the
|
||||||
|
- main map. */
|
||||||
|
- struct link_map **old_global
|
||||||
|
- = GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list;
|
||||||
|
- size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2);
|
||||||
|
-
|
||||||
|
- new_global = (struct link_map **)
|
||||||
|
- malloc (new_nalloc * sizeof (struct link_map *));
|
||||||
|
+ size_t allocation_size;
|
||||||
|
+ if (__builtin_mul_overflow (new_size, sizeof (struct link_map *),
|
||||||
|
+ &allocation_size))
|
||||||
|
+ add_to_global_resize_failure (new);
|
||||||
|
+ struct link_map **new_global = malloc (allocation_size);
|
||||||
|
if (new_global == NULL)
|
||||||
|
- goto nomem;
|
||||||
|
+ add_to_global_resize_failure (new);
|
||||||
|
|
||||||
|
- memcpy (new_global, old_global,
|
||||||
|
- ns->_ns_global_scope_alloc * sizeof (struct link_map *));
|
||||||
|
+ /* Copy over the old entries. */
|
||||||
|
+ memcpy (new_global, ns->_ns_main_searchlist->r_list,
|
||||||
|
+ ns->_ns_main_searchlist->r_nlist * sizeof (struct link_map *));
|
||||||
|
|
||||||
|
- ns->_ns_global_scope_alloc = new_nalloc;
|
||||||
|
+ ns->_ns_global_scope_alloc = new_size;
|
||||||
|
ns->_ns_main_searchlist->r_list = new_global;
|
||||||
|
|
||||||
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
|
@@ -131,16 +151,28 @@ add_to_global (struct link_map *new)
|
||||||
|
|
||||||
|
free (old_global);
|
||||||
|
}
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Actually add the new global objects to the global scope. Must be
|
||||||
|
+ called after add_to_global_resize. This function cannot fail. */
|
||||||
|
+static void
|
||||||
|
+add_to_global_update (struct link_map *new)
|
||||||
|
+{
|
||||||
|
+ struct link_namespaces *ns = &GL (dl_ns)[new->l_ns];
|
||||||
|
|
||||||
|
/* Now add the new entries. */
|
||||||
|
unsigned int new_nlist = ns->_ns_main_searchlist->r_nlist;
|
||||||
|
- for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
||||||
|
+ for (unsigned int cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
||||||
|
{
|
||||||
|
struct link_map *map = new->l_searchlist.r_list[cnt];
|
||||||
|
|
||||||
|
if (map->l_global == 0)
|
||||||
|
{
|
||||||
|
map->l_global = 1;
|
||||||
|
+
|
||||||
|
+ /* The array has been resized by add_to_global_resize. */
|
||||||
|
+ assert (new_nlist < ns->_ns_global_scope_alloc);
|
||||||
|
+
|
||||||
|
ns->_ns_main_searchlist->r_list[new_nlist++] = map;
|
||||||
|
|
||||||
|
/* We modify the global scope. Report this. */
|
||||||
|
@@ -149,10 +181,15 @@ add_to_global (struct link_map *new)
|
||||||
|
map->l_name, map->l_ns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* Some of the pending adds have been performed by the loop above.
|
||||||
|
+ Adjust the counter accordingly. */
|
||||||
|
+ unsigned int added = new_nlist - ns->_ns_main_searchlist->r_nlist;
|
||||||
|
+ assert (added <= ns->_ns_global_scope_pending_adds);
|
||||||
|
+ ns->_ns_global_scope_pending_adds -= added;
|
||||||
|
+
|
||||||
|
atomic_write_barrier ();
|
||||||
|
ns->_ns_main_searchlist->r_nlist = new_nlist;
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search link maps in all namespaces for the DSO that contains the object at
|
||||||
|
@@ -225,6 +262,10 @@ dl_open_worker (void *a)
|
||||||
|
args->nsid = call_map->l_ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Retain the old value, so that it can be restored. */
|
||||||
|
+ args->original_global_scope_pending_adds
|
||||||
|
+ = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
|
||||||
|
+
|
||||||
|
/* One might be tempted to assert that we are RT_CONSISTENT at this point, but that
|
||||||
|
may not be true if this is a recursive call to dlopen. */
|
||||||
|
_dl_debug_initialize (0, args->nsid);
|
||||||
|
@@ -266,7 +307,10 @@ dl_open_worker (void *a)
|
||||||
|
/* If the user requested the object to be in the global namespace
|
||||||
|
but it is not so far, add it now. */
|
||||||
|
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
||||||
|
- (void) add_to_global (new);
|
||||||
|
+ {
|
||||||
|
+ add_to_global_resize (new);
|
||||||
|
+ add_to_global_update (new);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
|
||||||
|
|
||||||
|
@@ -523,6 +567,11 @@ TLS generation counter wrapped! Please report this."));
|
||||||
|
DL_STATIC_INIT (new);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+ /* Perform the necessary allocations for adding new global objects
|
||||||
|
+ to the global scope below, via add_to_global_update. */
|
||||||
|
+ if (mode & RTLD_GLOBAL)
|
||||||
|
+ add_to_global_resize (new);
|
||||||
|
+
|
||||||
|
/* Run the initializer functions of new objects. Temporarily
|
||||||
|
disable the exception handler, so that lazy binding failures are
|
||||||
|
fatal. */
|
||||||
|
@@ -539,10 +588,7 @@ TLS generation counter wrapped! Please report this."));
|
||||||
|
|
||||||
|
/* Now we can make the new map available in the global scope. */
|
||||||
|
if (mode & RTLD_GLOBAL)
|
||||||
|
- /* Move the object in the global namespace. */
|
||||||
|
- if (add_to_global (new) != 0)
|
||||||
|
- /* It failed. */
|
||||||
|
- return;
|
||||||
|
+ add_to_global_update (new);
|
||||||
|
|
||||||
|
#ifndef SHARED
|
||||||
|
/* We must be the static _dl_open in libc.a. A static program that
|
||||||
|
@@ -556,7 +602,6 @@ TLS generation counter wrapped! Please report this."));
|
||||||
|
new->l_name, new->l_ns, new->l_direct_opencount);
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
void *
|
||||||
|
_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
|
||||||
|
int argc, char *argv[], char *env[])
|
||||||
|
@@ -624,6 +669,19 @@ no more namespaces available for dlmopen()"));
|
||||||
|
_dl_unload_cache ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+ /* Do this for both the error and success cases. The old value has
|
||||||
|
+ only been determined if the namespace ID was assigned (i.e., it
|
||||||
|
+ is not __LM_ID_CALLER). In the success case, we actually may
|
||||||
|
+ have consumed more pending adds than planned (because the local
|
||||||
|
+ scopes overlap in case of a recursive dlopen, the inner dlopen
|
||||||
|
+ doing some of the globalization work of the outer dlopen), so the
|
||||||
|
+ old pending adds value is larger than absolutely necessary.
|
||||||
|
+ Since it is just a conservative upper bound, this is harmless.
|
||||||
|
+ The top-level dlopen call will restore the field to zero. */
|
||||||
|
+ if (args.nsid >= 0)
|
||||||
|
+ GL (dl_ns)[args.nsid]._ns_global_scope_pending_adds
|
||||||
|
+ = args.original_global_scope_pending_adds;
|
||||||
|
+
|
||||||
|
/* See if an error occurred during loading. */
|
||||||
|
if (__glibc_unlikely (exception.errstring != NULL))
|
||||||
|
{
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index 6c5298a80bff8e96..57fbefea3cb841e9 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -311,7 +311,14 @@ struct rtld_global
|
||||||
|
/* This is zero at program start to signal that the global scope map is
|
||||||
|
allocated by rtld. Later it keeps the size of the map. It might be
|
||||||
|
reset if in _dl_close if the last global object is removed. */
|
||||||
|
- size_t _ns_global_scope_alloc;
|
||||||
|
+ unsigned int _ns_global_scope_alloc;
|
||||||
|
+
|
||||||
|
+ /* During dlopen, this is the number of objects that still need to
|
||||||
|
+ be added to the global scope map. It has to be taken into
|
||||||
|
+ account when resizing the map, for future map additions after
|
||||||
|
+ recursive dlopen calls from ELF constructors. */
|
||||||
|
+ unsigned int _ns_global_scope_pending_adds;
|
||||||
|
+
|
||||||
|
/* Search table for unique objects. */
|
||||||
|
struct unique_sym_table
|
||||||
|
{
|
490
SOURCES/glibc-rh1410154-7.patch
Normal file
490
SOURCES/glibc-rh1410154-7.patch
Normal file
@ -0,0 +1,490 @@
|
|||||||
|
commit a509eb117fac1d764b15eba64993f4bdb63d7f3c
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Nov 27 16:37:17 2019 +0100
|
||||||
|
|
||||||
|
Avoid late dlopen failure due to scope, TLS slotinfo updates [BZ #25112]
|
||||||
|
|
||||||
|
This change splits the scope and TLS slotinfo updates in dlopen into
|
||||||
|
two parts: one to resize the data structures, and one to actually apply
|
||||||
|
the update. The call to add_to_global_resize in dl_open_worker is moved
|
||||||
|
before the demarcation point at which no further memory allocations are
|
||||||
|
allowed.
|
||||||
|
|
||||||
|
_dl_add_to_slotinfo is adjusted to make the list update optional. There
|
||||||
|
is some optimization possibility here because we could grow the slotinfo
|
||||||
|
list of arrays in a single call, one the largest TLS modid is known.
|
||||||
|
|
||||||
|
This commit does not fix the fatal meory allocation failure in
|
||||||
|
_dl_update_slotinfo. Ideally, this error during dlopen should be
|
||||||
|
recoverable.
|
||||||
|
|
||||||
|
The update order of scopes and TLS data structures is retained, although
|
||||||
|
it appears to be more correct to fully initialize TLS first, and then
|
||||||
|
expose symbols in the newly loaded objects via the scope update.
|
||||||
|
|
||||||
|
Tested on x86_64-linux-gnu.
|
||||||
|
|
||||||
|
Change-Id: I240c58387dabda3ca1bcab48b02115175fa83d6c
|
||||||
|
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index 85db4f0ecb5f29ce..b330cff7d349224a 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -33,6 +33,7 @@
|
||||||
|
#include <stap-probe.h>
|
||||||
|
#include <atomic.h>
|
||||||
|
#include <libc-internal.h>
|
||||||
|
+#include <array_length.h>
|
||||||
|
|
||||||
|
#include <dl-dst.h>
|
||||||
|
#include <dl-prop.h>
|
||||||
|
@@ -214,6 +215,215 @@ _dl_find_dso_for_object (const ElfW(Addr) addr)
|
||||||
|
}
|
||||||
|
rtld_hidden_def (_dl_find_dso_for_object);
|
||||||
|
|
||||||
|
+/* Return true if NEW is found in the scope for MAP. */
|
||||||
|
+static size_t
|
||||||
|
+scope_has_map (struct link_map *map, struct link_map *new)
|
||||||
|
+{
|
||||||
|
+ size_t cnt;
|
||||||
|
+ for (cnt = 0; map->l_scope[cnt] != NULL; ++cnt)
|
||||||
|
+ if (map->l_scope[cnt] == &new->l_searchlist)
|
||||||
|
+ return true;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Return the length of the scope for MAP. */
|
||||||
|
+static size_t
|
||||||
|
+scope_size (struct link_map *map)
|
||||||
|
+{
|
||||||
|
+ size_t cnt;
|
||||||
|
+ for (cnt = 0; map->l_scope[cnt] != NULL; )
|
||||||
|
+ ++cnt;
|
||||||
|
+ return cnt;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Resize the scopes of depended-upon objects, so that the new object
|
||||||
|
+ can be added later without further allocation of memory. This
|
||||||
|
+ function can raise an exceptions due to malloc failure. */
|
||||||
|
+static void
|
||||||
|
+resize_scopes (struct link_map *new)
|
||||||
|
+{
|
||||||
|
+ /* If the file is not loaded now as a dependency, add the search
|
||||||
|
+ list of the newly loaded object to the scope. */
|
||||||
|
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||||
|
+ {
|
||||||
|
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
||||||
|
+
|
||||||
|
+ /* If the initializer has been called already, the object has
|
||||||
|
+ not been loaded here and now. */
|
||||||
|
+ if (imap->l_init_called && imap->l_type == lt_loaded)
|
||||||
|
+ {
|
||||||
|
+ if (scope_has_map (imap, new))
|
||||||
|
+ /* Avoid duplicates. */
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ size_t cnt = scope_size (imap);
|
||||||
|
+ if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max))
|
||||||
|
+ {
|
||||||
|
+ /* The l_scope array is too small. Allocate a new one
|
||||||
|
+ dynamically. */
|
||||||
|
+ size_t new_size;
|
||||||
|
+ struct r_scope_elem **newp;
|
||||||
|
+
|
||||||
|
+ if (imap->l_scope != imap->l_scope_mem
|
||||||
|
+ && imap->l_scope_max < array_length (imap->l_scope_mem))
|
||||||
|
+ {
|
||||||
|
+ /* If the current l_scope memory is not pointing to
|
||||||
|
+ the static memory in the structure, but the
|
||||||
|
+ static memory in the structure is large enough to
|
||||||
|
+ use for cnt + 1 scope entries, then switch to
|
||||||
|
+ using the static memory. */
|
||||||
|
+ new_size = array_length (imap->l_scope_mem);
|
||||||
|
+ newp = imap->l_scope_mem;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ new_size = imap->l_scope_max * 2;
|
||||||
|
+ newp = (struct r_scope_elem **)
|
||||||
|
+ malloc (new_size * sizeof (struct r_scope_elem *));
|
||||||
|
+ if (newp == NULL)
|
||||||
|
+ _dl_signal_error (ENOMEM, "dlopen", NULL,
|
||||||
|
+ N_("cannot create scope list"));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Copy the array and the terminating NULL. */
|
||||||
|
+ memcpy (newp, imap->l_scope,
|
||||||
|
+ (cnt + 1) * sizeof (imap->l_scope[0]));
|
||||||
|
+ struct r_scope_elem **old = imap->l_scope;
|
||||||
|
+
|
||||||
|
+ imap->l_scope = newp;
|
||||||
|
+
|
||||||
|
+ if (old != imap->l_scope_mem)
|
||||||
|
+ _dl_scope_free (old);
|
||||||
|
+
|
||||||
|
+ imap->l_scope_max = new_size;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Second stage of resize_scopes: Add NEW to the scopes. Also print
|
||||||
|
+ debugging information about scopes if requested.
|
||||||
|
+
|
||||||
|
+ This function cannot raise an exception because all required memory
|
||||||
|
+ has been allocated by a previous call to resize_scopes. */
|
||||||
|
+static void
|
||||||
|
+update_scopes (struct link_map *new)
|
||||||
|
+{
|
||||||
|
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||||
|
+ {
|
||||||
|
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
||||||
|
+ int from_scope = 0;
|
||||||
|
+
|
||||||
|
+ if (imap->l_init_called && imap->l_type == lt_loaded)
|
||||||
|
+ {
|
||||||
|
+ if (scope_has_map (imap, new))
|
||||||
|
+ /* Avoid duplicates. */
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ size_t cnt = scope_size (imap);
|
||||||
|
+ /* Assert that resize_scopes has sufficiently enlarged the
|
||||||
|
+ array. */
|
||||||
|
+ assert (cnt + 1 < imap->l_scope_max);
|
||||||
|
+
|
||||||
|
+ /* First terminate the extended list. Otherwise a thread
|
||||||
|
+ might use the new last element and then use the garbage
|
||||||
|
+ at offset IDX+1. */
|
||||||
|
+ imap->l_scope[cnt + 1] = NULL;
|
||||||
|
+ atomic_write_barrier ();
|
||||||
|
+ imap->l_scope[cnt] = &new->l_searchlist;
|
||||||
|
+
|
||||||
|
+ from_scope = cnt;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Print scope information. */
|
||||||
|
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
|
||||||
|
+ _dl_show_scope (imap, from_scope);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Call _dl_add_to_slotinfo with DO_ADD set to false, to allocate
|
||||||
|
+ space in GL (dl_tls_dtv_slotinfo_list). This can raise an
|
||||||
|
+ exception. The return value is true if any of the new objects use
|
||||||
|
+ TLS. */
|
||||||
|
+static bool
|
||||||
|
+resize_tls_slotinfo (struct link_map *new)
|
||||||
|
+{
|
||||||
|
+ bool any_tls = false;
|
||||||
|
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||||
|
+ {
|
||||||
|
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
||||||
|
+
|
||||||
|
+ /* Only add TLS memory if this object is loaded now and
|
||||||
|
+ therefore is not yet initialized. */
|
||||||
|
+ if (! imap->l_init_called && imap->l_tls_blocksize > 0)
|
||||||
|
+ {
|
||||||
|
+ _dl_add_to_slotinfo (imap, false);
|
||||||
|
+ any_tls = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return any_tls;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Second stage of TLS update, after resize_tls_slotinfo. This
|
||||||
|
+ function does not raise any exception. It should only be called if
|
||||||
|
+ resize_tls_slotinfo returned true. */
|
||||||
|
+static void
|
||||||
|
+update_tls_slotinfo (struct link_map *new)
|
||||||
|
+{
|
||||||
|
+ unsigned int first_static_tls = new->l_searchlist.r_nlist;
|
||||||
|
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||||
|
+ {
|
||||||
|
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
||||||
|
+
|
||||||
|
+ /* Only add TLS memory if this object is loaded now and
|
||||||
|
+ therefore is not yet initialized. */
|
||||||
|
+ if (! imap->l_init_called && imap->l_tls_blocksize > 0)
|
||||||
|
+ {
|
||||||
|
+ _dl_add_to_slotinfo (imap, true);
|
||||||
|
+
|
||||||
|
+ if (imap->l_need_tls_init
|
||||||
|
+ && first_static_tls == new->l_searchlist.r_nlist)
|
||||||
|
+ first_static_tls = i;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
|
||||||
|
+ _dl_fatal_printf (N_("\
|
||||||
|
+TLS generation counter wrapped! Please report this."));
|
||||||
|
+
|
||||||
|
+ /* We need a second pass for static tls data, because
|
||||||
|
+ _dl_update_slotinfo must not be run while calls to
|
||||||
|
+ _dl_add_to_slotinfo are still pending. */
|
||||||
|
+ for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
|
||||||
|
+ {
|
||||||
|
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
||||||
|
+
|
||||||
|
+ if (imap->l_need_tls_init
|
||||||
|
+ && ! imap->l_init_called
|
||||||
|
+ && imap->l_tls_blocksize > 0)
|
||||||
|
+ {
|
||||||
|
+ /* For static TLS we have to allocate the memory here and
|
||||||
|
+ now, but we can delay updating the DTV. */
|
||||||
|
+ imap->l_need_tls_init = 0;
|
||||||
|
+#ifdef SHARED
|
||||||
|
+ /* Update the slot information data for at least the
|
||||||
|
+ generation of the DSO we are allocating data for. */
|
||||||
|
+
|
||||||
|
+ /* FIXME: This can terminate the process on memory
|
||||||
|
+ allocation failure. It is not possible to raise
|
||||||
|
+ exceptions from this context; to fix this bug,
|
||||||
|
+ _dl_update_slotinfo would have to be split into two
|
||||||
|
+ operations, similar to resize_scopes and update_scopes
|
||||||
|
+ above. This is related to bug 16134. */
|
||||||
|
+ _dl_update_slotinfo (imap->l_tls_modid);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ GL(dl_init_static_tls) (imap);
|
||||||
|
+ assert (imap->l_need_tls_init == 0);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* struct dl_init_args and call_dl_init are used to call _dl_init with
|
||||||
|
exception handling disabled. */
|
||||||
|
struct dl_init_args
|
||||||
|
@@ -431,133 +641,40 @@ dl_open_worker (void *a)
|
||||||
|
relocation. */
|
||||||
|
_dl_open_check (new);
|
||||||
|
|
||||||
|
- /* If the file is not loaded now as a dependency, add the search
|
||||||
|
- list of the newly loaded object to the scope. */
|
||||||
|
- bool any_tls = false;
|
||||||
|
- unsigned int first_static_tls = new->l_searchlist.r_nlist;
|
||||||
|
- for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||||
|
- {
|
||||||
|
- struct link_map *imap = new->l_searchlist.r_list[i];
|
||||||
|
- int from_scope = 0;
|
||||||
|
+ /* This only performs the memory allocations. The actual update of
|
||||||
|
+ the scopes happens below, after failure is impossible. */
|
||||||
|
+ resize_scopes (new);
|
||||||
|
|
||||||
|
- /* If the initializer has been called already, the object has
|
||||||
|
- not been loaded here and now. */
|
||||||
|
- if (imap->l_init_called && imap->l_type == lt_loaded)
|
||||||
|
- {
|
||||||
|
- struct r_scope_elem **runp = imap->l_scope;
|
||||||
|
- size_t cnt = 0;
|
||||||
|
-
|
||||||
|
- while (*runp != NULL)
|
||||||
|
- {
|
||||||
|
- if (*runp == &new->l_searchlist)
|
||||||
|
- break;
|
||||||
|
- ++cnt;
|
||||||
|
- ++runp;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (*runp != NULL)
|
||||||
|
- /* Avoid duplicates. */
|
||||||
|
- continue;
|
||||||
|
-
|
||||||
|
- if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max))
|
||||||
|
- {
|
||||||
|
- /* The 'r_scope' array is too small. Allocate a new one
|
||||||
|
- dynamically. */
|
||||||
|
- size_t new_size;
|
||||||
|
- struct r_scope_elem **newp;
|
||||||
|
-
|
||||||
|
-#define SCOPE_ELEMS(imap) \
|
||||||
|
- (sizeof (imap->l_scope_mem) / sizeof (imap->l_scope_mem[0]))
|
||||||
|
+ /* Increase the size of the GL (dl_tls_dtv_slotinfo_list) data
|
||||||
|
+ structure. */
|
||||||
|
+ bool any_tls = resize_tls_slotinfo (new);
|
||||||
|
|
||||||
|
- if (imap->l_scope != imap->l_scope_mem
|
||||||
|
- && imap->l_scope_max < SCOPE_ELEMS (imap))
|
||||||
|
- {
|
||||||
|
- new_size = SCOPE_ELEMS (imap);
|
||||||
|
- newp = imap->l_scope_mem;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- new_size = imap->l_scope_max * 2;
|
||||||
|
- newp = (struct r_scope_elem **)
|
||||||
|
- malloc (new_size * sizeof (struct r_scope_elem *));
|
||||||
|
- if (newp == NULL)
|
||||||
|
- _dl_signal_error (ENOMEM, "dlopen", NULL,
|
||||||
|
- N_("cannot create scope list"));
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- memcpy (newp, imap->l_scope, cnt * sizeof (imap->l_scope[0]));
|
||||||
|
- struct r_scope_elem **old = imap->l_scope;
|
||||||
|
-
|
||||||
|
- imap->l_scope = newp;
|
||||||
|
-
|
||||||
|
- if (old != imap->l_scope_mem)
|
||||||
|
- _dl_scope_free (old);
|
||||||
|
-
|
||||||
|
- imap->l_scope_max = new_size;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* First terminate the extended list. Otherwise a thread
|
||||||
|
- might use the new last element and then use the garbage
|
||||||
|
- at offset IDX+1. */
|
||||||
|
- imap->l_scope[cnt + 1] = NULL;
|
||||||
|
- atomic_write_barrier ();
|
||||||
|
- imap->l_scope[cnt] = &new->l_searchlist;
|
||||||
|
-
|
||||||
|
- /* Print only new scope information. */
|
||||||
|
- from_scope = cnt;
|
||||||
|
- }
|
||||||
|
- /* Only add TLS memory if this object is loaded now and
|
||||||
|
- therefore is not yet initialized. */
|
||||||
|
- else if (! imap->l_init_called
|
||||||
|
- /* Only if the module defines thread local data. */
|
||||||
|
- && __builtin_expect (imap->l_tls_blocksize > 0, 0))
|
||||||
|
- {
|
||||||
|
- /* Now that we know the object is loaded successfully add
|
||||||
|
- modules containing TLS data to the slot info table. We
|
||||||
|
- might have to increase its size. */
|
||||||
|
- _dl_add_to_slotinfo (imap);
|
||||||
|
-
|
||||||
|
- if (imap->l_need_tls_init
|
||||||
|
- && first_static_tls == new->l_searchlist.r_nlist)
|
||||||
|
- first_static_tls = i;
|
||||||
|
-
|
||||||
|
- /* We have to bump the generation counter. */
|
||||||
|
- any_tls = true;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* Print scope information. */
|
||||||
|
- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
|
||||||
|
- _dl_show_scope (imap, from_scope);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* Bump the generation number if necessary. */
|
||||||
|
- if (any_tls && __builtin_expect (++GL(dl_tls_generation) == 0, 0))
|
||||||
|
- _dl_fatal_printf (N_("\
|
||||||
|
-TLS generation counter wrapped! Please report this."));
|
||||||
|
-
|
||||||
|
- /* We need a second pass for static tls data, because _dl_update_slotinfo
|
||||||
|
- must not be run while calls to _dl_add_to_slotinfo are still pending. */
|
||||||
|
- for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
|
||||||
|
- {
|
||||||
|
- struct link_map *imap = new->l_searchlist.r_list[i];
|
||||||
|
-
|
||||||
|
- if (imap->l_need_tls_init
|
||||||
|
- && ! imap->l_init_called
|
||||||
|
- && imap->l_tls_blocksize > 0)
|
||||||
|
- {
|
||||||
|
- /* For static TLS we have to allocate the memory here and
|
||||||
|
- now, but we can delay updating the DTV. */
|
||||||
|
- imap->l_need_tls_init = 0;
|
||||||
|
-#ifdef SHARED
|
||||||
|
- /* Update the slot information data for at least the
|
||||||
|
- generation of the DSO we are allocating data for. */
|
||||||
|
- _dl_update_slotinfo (imap->l_tls_modid);
|
||||||
|
-#endif
|
||||||
|
+ /* Perform the necessary allocations for adding new global objects
|
||||||
|
+ to the global scope below. */
|
||||||
|
+ if (mode & RTLD_GLOBAL)
|
||||||
|
+ add_to_global_resize (new);
|
||||||
|
|
||||||
|
- GL(dl_init_static_tls) (imap);
|
||||||
|
- assert (imap->l_need_tls_init == 0);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ /* Demarcation point: After this, no recoverable errors are allowed.
|
||||||
|
+ All memory allocations for new objects must have happened
|
||||||
|
+ before. */
|
||||||
|
+
|
||||||
|
+ /* Second stage after resize_scopes: Actually perform the scope
|
||||||
|
+ update. After this, dlsym and lazy binding can bind to new
|
||||||
|
+ objects. */
|
||||||
|
+ update_scopes (new);
|
||||||
|
+
|
||||||
|
+ /* FIXME: It is unclear whether the order here is correct.
|
||||||
|
+ Shouldn't new objects be made available for binding (and thus
|
||||||
|
+ execution) only after there TLS data has been set up fully?
|
||||||
|
+ Fixing bug 16134 will likely make this distinction less
|
||||||
|
+ important. */
|
||||||
|
+
|
||||||
|
+ /* Second stage after resize_tls_slotinfo: Update the slotinfo data
|
||||||
|
+ structures. */
|
||||||
|
+ if (any_tls)
|
||||||
|
+ /* FIXME: This calls _dl_update_slotinfo, which aborts the process
|
||||||
|
+ on memory allocation failure. See bug 16134. */
|
||||||
|
+ update_tls_slotinfo (new);
|
||||||
|
|
||||||
|
/* Notify the debugger all new objects have been relocated. */
|
||||||
|
if (relocation_in_progress)
|
||||||
|
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||||
|
index c87caf13d6a97ba4..a2def280b7096960 100644
|
||||||
|
--- a/elf/dl-tls.c
|
||||||
|
+++ b/elf/dl-tls.c
|
||||||
|
@@ -883,7 +883,7 @@ _dl_tls_get_addr_soft (struct link_map *l)
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
-_dl_add_to_slotinfo (struct link_map *l)
|
||||||
|
+_dl_add_to_slotinfo (struct link_map *l, bool do_add)
|
||||||
|
{
|
||||||
|
/* Now that we know the object is loaded successfully add
|
||||||
|
modules containing TLS data to the dtv info table. We
|
||||||
|
@@ -939,6 +939,9 @@ cannot create TLS data structures"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the information into the slotinfo data structure. */
|
||||||
|
- listp->slotinfo[idx].map = l;
|
||||||
|
- listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
|
||||||
|
+ if (do_add)
|
||||||
|
+ {
|
||||||
|
+ listp->slotinfo[idx].map = l;
|
||||||
|
+ listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index 4ec26a79cbb0aa4f..0aa1a2a19f649e16 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -2167,7 +2167,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||||
|
|
||||||
|
/* Add object to slot information data if necessasy. */
|
||||||
|
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
||||||
|
- _dl_add_to_slotinfo (l);
|
||||||
|
+ _dl_add_to_slotinfo (l, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
@@ -2215,7 +2215,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||||
|
|
||||||
|
/* Add object to slot information data if necessasy. */
|
||||||
|
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
||||||
|
- _dl_add_to_slotinfo (l);
|
||||||
|
+ _dl_add_to_slotinfo (l, true);
|
||||||
|
}
|
||||||
|
HP_TIMING_NOW (stop);
|
||||||
|
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index 57fbefea3cb841e9..c6b7e61badbfd513 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -1135,8 +1135,15 @@ extern void *_dl_open (const char *name, int mode, const void *caller,
|
||||||
|
old scope, OLD can't be freed until no thread is using it. */
|
||||||
|
extern int _dl_scope_free (void *) attribute_hidden;
|
||||||
|
|
||||||
|
-/* Add module to slot information data. */
|
||||||
|
-extern void _dl_add_to_slotinfo (struct link_map *l) attribute_hidden;
|
||||||
|
+
|
||||||
|
+/* Add module to slot information data. If DO_ADD is false, only the
|
||||||
|
+ required memory is allocated. Must be called with GL
|
||||||
|
+ (dl_load_lock) acquired. If the function has already been called
|
||||||
|
+ for the link map L with !do_add, then this function will not raise
|
||||||
|
+ an exception, otherwise it is possible that it encounters a memory
|
||||||
|
+ allocation failure. */
|
||||||
|
+extern void _dl_add_to_slotinfo (struct link_map *l, bool do_add)
|
||||||
|
+ attribute_hidden;
|
||||||
|
|
||||||
|
/* Update slot information data for at least the generation of the
|
||||||
|
module with the given index. */
|
619
SOURCES/glibc-rh1410154-8.patch
Normal file
619
SOURCES/glibc-rh1410154-8.patch
Normal file
@ -0,0 +1,619 @@
|
|||||||
|
commit f63b73814f74032c0e5d0a83300e3d864ef905e5
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Nov 13 15:44:56 2019 +0100
|
||||||
|
|
||||||
|
Remove all loaded objects if dlopen fails, ignoring NODELETE [BZ #20839]
|
||||||
|
|
||||||
|
This introduces a “pending NODELETE” state in the link map, which is
|
||||||
|
flipped to the persistent NODELETE state late in dlopen, via
|
||||||
|
activate_nodelete. During initial relocation, symbol binding
|
||||||
|
records pending NODELETE state only. dlclose ignores pending NODELETE
|
||||||
|
state. Taken together, this results that a partially completed dlopen
|
||||||
|
is rolled back completely because new NODELETE mappings are unloaded.
|
||||||
|
|
||||||
|
Tested on x86_64-linux-gnu and i386-linux-gnu.
|
||||||
|
|
||||||
|
Change-Id: Ib2a3d86af6f92d75baca65431d74783ee0dbc292
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile
|
||||||
|
(Usual conflicts due to test backport differences.)
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index b752f6366400d221..bf7c41f38be42184 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -191,7 +191,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
|
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
|
||||||
|
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
||||||
|
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
||||||
|
- tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail
|
||||||
|
+ tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \
|
||||||
|
+ tst-dlopenfail
|
||||||
|
# reldep9
|
||||||
|
tests-internal += loadtest unload unload2 circleload1 \
|
||||||
|
neededtest neededtest2 neededtest3 neededtest4 \
|
||||||
|
@@ -282,7 +283,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||||
|
tst-absolute-zero-lib tst-big-note-lib \
|
||||||
|
tst-sonamemove-linkmod1 \
|
||||||
|
tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
|
||||||
|
- tst-initlazyfailmod tst-finilazyfailmod
|
||||||
|
+ tst-initlazyfailmod tst-finilazyfailmod \
|
||||||
|
+ tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2
|
||||||
|
|
||||||
|
ifeq (yes,$(have-mtls-dialect-gnu2))
|
||||||
|
tests += tst-gnu2-tls1
|
||||||
|
@@ -1537,3 +1539,13 @@ LDFLAGS-tst-initlazyfailmod.so = \
|
||||||
|
-Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
|
||||||
|
LDFLAGS-tst-finilazyfailmod.so = \
|
||||||
|
-Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
|
||||||
|
+
|
||||||
|
+$(objpfx)tst-dlopenfail: $(libdl)
|
||||||
|
+$(objpfx)tst-dlopenfail.out: \
|
||||||
|
+ $(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so
|
||||||
|
+# Order matters here. tst-dlopenfaillinkmod.so's soname ensures
|
||||||
|
+# a run-time loader failure.
|
||||||
|
+$(objpfx)tst-dlopenfailmod1.so: \
|
||||||
|
+ $(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so
|
||||||
|
+LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so
|
||||||
|
+$(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library)
|
||||||
|
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||||
|
index 88aeea25839a34e0..243a028c443173c1 100644
|
||||||
|
--- a/elf/dl-close.c
|
||||||
|
+++ b/elf/dl-close.c
|
||||||
|
@@ -168,14 +168,6 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
char done[nloaded];
|
||||||
|
struct link_map *maps[nloaded];
|
||||||
|
|
||||||
|
- /* Clear DF_1_NODELETE to force object deletion. We don't need to touch
|
||||||
|
- l_tls_dtor_count because forced object deletion only happens when an
|
||||||
|
- error occurs during object load. Destructor registration for TLS
|
||||||
|
- non-POD objects should not have happened till then for this
|
||||||
|
- object. */
|
||||||
|
- if (force)
|
||||||
|
- map->l_flags_1 &= ~DF_1_NODELETE;
|
||||||
|
-
|
||||||
|
/* Run over the list and assign indexes to the link maps and enter
|
||||||
|
them into the MAPS array. */
|
||||||
|
int idx = 0;
|
||||||
|
@@ -205,7 +197,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
/* Check whether this object is still used. */
|
||||||
|
if (l->l_type == lt_loaded
|
||||||
|
&& l->l_direct_opencount == 0
|
||||||
|
- && (l->l_flags_1 & DF_1_NODELETE) == 0
|
||||||
|
+ && l->l_nodelete != link_map_nodelete_active
|
||||||
|
/* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why
|
||||||
|
acquire is sufficient and correct. */
|
||||||
|
&& atomic_load_acquire (&l->l_tls_dtor_count) == 0
|
||||||
|
@@ -288,7 +280,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
if (!used[i])
|
||||||
|
{
|
||||||
|
assert (imap->l_type == lt_loaded
|
||||||
|
- && (imap->l_flags_1 & DF_1_NODELETE) == 0);
|
||||||
|
+ && imap->l_nodelete != link_map_nodelete_active);
|
||||||
|
|
||||||
|
/* Call its termination function. Do not do it for
|
||||||
|
half-cooked objects. Temporarily disable exception
|
||||||
|
@@ -828,7 +820,7 @@ _dl_close (void *_map)
|
||||||
|
before we took the lock. There is no way to detect this (see below)
|
||||||
|
so we proceed assuming this isn't the case. First see whether we
|
||||||
|
can remove the object at all. */
|
||||||
|
- if (__glibc_unlikely (map->l_flags_1 & DF_1_NODELETE))
|
||||||
|
+ if (__glibc_unlikely (map->l_nodelete == link_map_nodelete_active))
|
||||||
|
{
|
||||||
|
/* Nope. Do nothing. */
|
||||||
|
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||||
|
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
||||||
|
index efbdb8deb3c0a9d4..c5e5857fb1fe2808 100644
|
||||||
|
--- a/elf/dl-lookup.c
|
||||||
|
+++ b/elf/dl-lookup.c
|
||||||
|
@@ -192,9 +192,10 @@ enter_unique_sym (struct unique_sym *table, size_t size,
|
||||||
|
Return the matching symbol in RESULT. */
|
||||||
|
static void
|
||||||
|
do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
||||||
|
- const struct link_map *map, struct sym_val *result,
|
||||||
|
+ struct link_map *map, struct sym_val *result,
|
||||||
|
int type_class, const ElfW(Sym) *sym, const char *strtab,
|
||||||
|
- const ElfW(Sym) *ref, const struct link_map *undef_map)
|
||||||
|
+ const ElfW(Sym) *ref, const struct link_map *undef_map,
|
||||||
|
+ int flags)
|
||||||
|
{
|
||||||
|
/* We have to determine whether we already found a symbol with this
|
||||||
|
name before. If not then we have to add it to the search table.
|
||||||
|
@@ -222,7 +223,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
||||||
|
copy from the copy addressed through the
|
||||||
|
relocation. */
|
||||||
|
result->s = sym;
|
||||||
|
- result->m = (struct link_map *) map;
|
||||||
|
+ result->m = map;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@@ -311,9 +312,19 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
||||||
|
new_hash, strtab + sym->st_name, sym, map);
|
||||||
|
|
||||||
|
if (map->l_type == lt_loaded)
|
||||||
|
- /* Make sure we don't unload this object by
|
||||||
|
- setting the appropriate flag. */
|
||||||
|
- ((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE;
|
||||||
|
+ {
|
||||||
|
+ /* Make sure we don't unload this object by
|
||||||
|
+ setting the appropriate flag. */
|
||||||
|
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
||||||
|
+ && map->l_nodelete == link_map_nodelete_inactive)
|
||||||
|
+ _dl_debug_printf ("\
|
||||||
|
+marking %s [%lu] as NODELETE due to unique symbol\n",
|
||||||
|
+ map->l_name, map->l_ns);
|
||||||
|
+ if (flags & DL_LOOKUP_FOR_RELOCATE)
|
||||||
|
+ map->l_nodelete = link_map_nodelete_pending;
|
||||||
|
+ else
|
||||||
|
+ map->l_nodelete = link_map_nodelete_active;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
++tab->n_elements;
|
||||||
|
|
||||||
|
@@ -525,8 +536,9 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case STB_GNU_UNIQUE:;
|
||||||
|
- do_lookup_unique (undef_name, new_hash, map, result, type_class,
|
||||||
|
- sym, strtab, ref, undef_map);
|
||||||
|
+ do_lookup_unique (undef_name, new_hash, (struct link_map *) map,
|
||||||
|
+ result, type_class, sym, strtab, ref,
|
||||||
|
+ undef_map, flags);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
@@ -568,9 +580,13 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
||||||
|
if (undef_map == map)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- /* Avoid references to objects which cannot be unloaded anyway. */
|
||||||
|
+ /* Avoid references to objects which cannot be unloaded anyway. We
|
||||||
|
+ do not need to record dependencies if this object goes away
|
||||||
|
+ during dlopen failure, either. IFUNC resolvers with relocation
|
||||||
|
+ dependencies may pick an dependency which can be dlclose'd, but
|
||||||
|
+ such IFUNC resolvers are undefined anyway. */
|
||||||
|
assert (map->l_type == lt_loaded);
|
||||||
|
- if ((map->l_flags_1 & DF_1_NODELETE) != 0)
|
||||||
|
+ if (map->l_nodelete != link_map_nodelete_inactive)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct link_map_reldeps *l_reldeps
|
||||||
|
@@ -678,16 +694,33 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
||||||
|
|
||||||
|
/* Redo the NODELETE check, as when dl_load_lock wasn't held
|
||||||
|
yet this could have changed. */
|
||||||
|
- if ((map->l_flags_1 & DF_1_NODELETE) != 0)
|
||||||
|
+ if (map->l_nodelete != link_map_nodelete_inactive)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* If the object with the undefined reference cannot be removed ever
|
||||||
|
just make sure the same is true for the object which contains the
|
||||||
|
definition. */
|
||||||
|
if (undef_map->l_type != lt_loaded
|
||||||
|
- || (undef_map->l_flags_1 & DF_1_NODELETE) != 0)
|
||||||
|
+ || (undef_map->l_nodelete != link_map_nodelete_inactive))
|
||||||
|
{
|
||||||
|
- map->l_flags_1 |= DF_1_NODELETE;
|
||||||
|
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
||||||
|
+ && map->l_nodelete == link_map_nodelete_inactive)
|
||||||
|
+ {
|
||||||
|
+ if (undef_map->l_name[0] == '\0')
|
||||||
|
+ _dl_debug_printf ("\
|
||||||
|
+marking %s [%lu] as NODELETE due to reference to main program\n",
|
||||||
|
+ map->l_name, map->l_ns);
|
||||||
|
+ else
|
||||||
|
+ _dl_debug_printf ("\
|
||||||
|
+marking %s [%lu] as NODELETE due to reference to %s [%lu]\n",
|
||||||
|
+ map->l_name, map->l_ns,
|
||||||
|
+ undef_map->l_name, undef_map->l_ns);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (flags & DL_LOOKUP_FOR_RELOCATE)
|
||||||
|
+ map->l_nodelete = link_map_nodelete_pending;
|
||||||
|
+ else
|
||||||
|
+ map->l_nodelete = link_map_nodelete_active;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -712,7 +745,18 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
||||||
|
no fatal problem. We simply make sure the referenced object
|
||||||
|
cannot be unloaded. This is semantically the correct
|
||||||
|
behavior. */
|
||||||
|
- map->l_flags_1 |= DF_1_NODELETE;
|
||||||
|
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
||||||
|
+ && map->l_nodelete == link_map_nodelete_inactive)
|
||||||
|
+ _dl_debug_printf ("\
|
||||||
|
+marking %s [%lu] as NODELETE due to memory allocation failure\n",
|
||||||
|
+ map->l_name, map->l_ns);
|
||||||
|
+ if (flags & DL_LOOKUP_FOR_RELOCATE)
|
||||||
|
+ /* In case of non-lazy binding, we could actually
|
||||||
|
+ report the memory allocation error, but for now, we
|
||||||
|
+ use the conservative approximation as well. */
|
||||||
|
+ map->l_nodelete = link_map_nodelete_pending;
|
||||||
|
+ else
|
||||||
|
+ map->l_nodelete = link_map_nodelete_active;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index b330cff7d349224a..79c6e4c8ed1c9dfa 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -424,6 +424,40 @@ TLS generation counter wrapped! Please report this."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Mark the objects as NODELETE if required. This is delayed until
|
||||||
|
+ after dlopen failure is not possible, so that _dl_close can clean
|
||||||
|
+ up objects if necessary. */
|
||||||
|
+static void
|
||||||
|
+activate_nodelete (struct link_map *new, int mode)
|
||||||
|
+{
|
||||||
|
+ if (mode & RTLD_NODELETE || new->l_nodelete == link_map_nodelete_pending)
|
||||||
|
+ {
|
||||||
|
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES))
|
||||||
|
+ _dl_debug_printf ("activating NODELETE for %s [%lu]\n",
|
||||||
|
+ new->l_name, new->l_ns);
|
||||||
|
+ new->l_nodelete = link_map_nodelete_active;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||||
|
+ {
|
||||||
|
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
||||||
|
+ if (imap->l_nodelete == link_map_nodelete_pending)
|
||||||
|
+ {
|
||||||
|
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES))
|
||||||
|
+ _dl_debug_printf ("activating NODELETE for %s [%lu]\n",
|
||||||
|
+ imap->l_name, imap->l_ns);
|
||||||
|
+
|
||||||
|
+ /* Only new objects should have set
|
||||||
|
+ link_map_nodelete_pending. Existing objects should not
|
||||||
|
+ have gained any new dependencies and therefore cannot
|
||||||
|
+ reach NODELETE status. */
|
||||||
|
+ assert (!imap->l_init_called || imap->l_type != lt_loaded);
|
||||||
|
+
|
||||||
|
+ imap->l_nodelete = link_map_nodelete_active;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* struct dl_init_args and call_dl_init are used to call _dl_init with
|
||||||
|
exception handling disabled. */
|
||||||
|
struct dl_init_args
|
||||||
|
@@ -493,12 +527,6 @@ dl_open_worker (void *a)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Mark the object as not deletable if the RTLD_NODELETE flags was passed.
|
||||||
|
- Do this early so that we don't skip marking the object if it was
|
||||||
|
- already loaded. */
|
||||||
|
- if (__glibc_unlikely (mode & RTLD_NODELETE))
|
||||||
|
- new->l_flags_1 |= DF_1_NODELETE;
|
||||||
|
-
|
||||||
|
if (__glibc_unlikely (mode & __RTLD_SPROF))
|
||||||
|
/* This happens only if we load a DSO for 'sprof'. */
|
||||||
|
return;
|
||||||
|
@@ -514,19 +542,37 @@ dl_open_worker (void *a)
|
||||||
|
_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
|
||||||
|
new->l_name, new->l_ns, new->l_direct_opencount);
|
||||||
|
|
||||||
|
- /* If the user requested the object to be in the global namespace
|
||||||
|
- but it is not so far, add it now. */
|
||||||
|
+ /* If the user requested the object to be in the global
|
||||||
|
+ namespace but it is not so far, prepare to add it now. This
|
||||||
|
+ can raise an exception to do a malloc failure. */
|
||||||
|
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
||||||
|
+ add_to_global_resize (new);
|
||||||
|
+
|
||||||
|
+ /* Mark the object as not deletable if the RTLD_NODELETE flags
|
||||||
|
+ was passed. */
|
||||||
|
+ if (__glibc_unlikely (mode & RTLD_NODELETE))
|
||||||
|
{
|
||||||
|
- add_to_global_resize (new);
|
||||||
|
- add_to_global_update (new);
|
||||||
|
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)
|
||||||
|
+ && new->l_nodelete == link_map_nodelete_inactive)
|
||||||
|
+ _dl_debug_printf ("marking %s [%lu] as NODELETE\n",
|
||||||
|
+ new->l_name, new->l_ns);
|
||||||
|
+ new->l_nodelete = link_map_nodelete_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Finalize the addition to the global scope. */
|
||||||
|
+ if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
||||||
|
+ add_to_global_update (new);
|
||||||
|
+
|
||||||
|
assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Schedule NODELETE marking for the directly loaded object if
|
||||||
|
+ requested. */
|
||||||
|
+ if (__glibc_unlikely (mode & RTLD_NODELETE))
|
||||||
|
+ new->l_nodelete = link_map_nodelete_pending;
|
||||||
|
+
|
||||||
|
/* Load that object's dependencies. */
|
||||||
|
_dl_map_object_deps (new, NULL, 0, 0,
|
||||||
|
mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
|
||||||
|
@@ -598,6 +644,14 @@ dl_open_worker (void *a)
|
||||||
|
|
||||||
|
int relocation_in_progress = 0;
|
||||||
|
|
||||||
|
+ /* Perform relocation. This can trigger lazy binding in IFUNC
|
||||||
|
+ resolvers. For NODELETE mappings, these dependencies are not
|
||||||
|
+ recorded because the flag has not been applied to the newly
|
||||||
|
+ loaded objects. This means that upon dlopen failure, these
|
||||||
|
+ NODELETE objects can be unloaded despite existing references to
|
||||||
|
+ them. However, such relocation dependencies in IFUNC resolvers
|
||||||
|
+ are undefined anyway, so this is not a problem. */
|
||||||
|
+
|
||||||
|
for (unsigned int i = nmaps; i-- > 0; )
|
||||||
|
{
|
||||||
|
l = maps[i];
|
||||||
|
@@ -627,7 +681,7 @@ dl_open_worker (void *a)
|
||||||
|
_dl_start_profile ();
|
||||||
|
|
||||||
|
/* Prevent unloading the object. */
|
||||||
|
- GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE;
|
||||||
|
+ GL(dl_profile_map)->l_nodelete = link_map_nodelete_active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
@@ -658,6 +712,8 @@ dl_open_worker (void *a)
|
||||||
|
All memory allocations for new objects must have happened
|
||||||
|
before. */
|
||||||
|
|
||||||
|
+ activate_nodelete (new, mode);
|
||||||
|
+
|
||||||
|
/* Second stage after resize_scopes: Actually perform the scope
|
||||||
|
update. After this, dlsym and lazy binding can bind to new
|
||||||
|
objects. */
|
||||||
|
@@ -817,6 +873,10 @@ no more namespaces available for dlmopen()"));
|
||||||
|
GL(dl_tls_dtv_gaps) = true;
|
||||||
|
|
||||||
|
_dl_close_worker (args.map, true);
|
||||||
|
+
|
||||||
|
+ /* All link_map_nodelete_pending objects should have been
|
||||||
|
+ deleted at this point, which is why it is not necessary
|
||||||
|
+ to reset the flag here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
|
||||||
|
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
|
||||||
|
index 4b1ea7c4078ee947..ea286abaea0128d1 100644
|
||||||
|
--- a/elf/get-dynamic-info.h
|
||||||
|
+++ b/elf/get-dynamic-info.h
|
||||||
|
@@ -163,6 +163,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||||
|
if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
|
||||||
|
{
|
||||||
|
l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
|
||||||
|
+ if (l->l_flags_1 & DF_1_NODELETE)
|
||||||
|
+ l->l_nodelete = link_map_nodelete_pending;
|
||||||
|
|
||||||
|
/* Only DT_1_SUPPORTED_MASK bits are supported, and we would like
|
||||||
|
to assert this, but we can't. Users have been setting
|
||||||
|
diff --git a/elf/tst-dlopenfail.c b/elf/tst-dlopenfail.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..ce3140c899562ca8
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-dlopenfail.c
|
||||||
|
@@ -0,0 +1,79 @@
|
||||||
|
+/* Test dlopen rollback after failures involving NODELETE objects (bug 20839).
|
||||||
|
+ Copyright (C) 2019 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 <dlfcn.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <gnu/lib-names.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xdlfcn.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* This test uses libpthread as the canonical NODELETE module. If
|
||||||
|
+ libpthread is no longer NODELETE because it has been merged into
|
||||||
|
+ libc, the test needs to be updated. */
|
||||||
|
+ TEST_VERIFY (dlsym (NULL, "pthread_create") == NULL);
|
||||||
|
+
|
||||||
|
+ /* This is expected to fail because of the missing dependency. */
|
||||||
|
+ puts ("info: attempting to load tst-dlopenfailmod1.so");
|
||||||
|
+ TEST_VERIFY (dlopen ("tst-dlopenfailmod1.so", RTLD_LAZY) == NULL);
|
||||||
|
+ const char *message = dlerror ();
|
||||||
|
+ TEST_COMPARE_STRING (message,
|
||||||
|
+ "tst-dlopenfail-missingmod.so:"
|
||||||
|
+ " cannot open shared object file:"
|
||||||
|
+ " No such file or directory");
|
||||||
|
+
|
||||||
|
+ /* Do not probe for the presence of libpthread at this point because
|
||||||
|
+ that might trigger relocation if bug 20839 is present, obscuring
|
||||||
|
+ a subsequent crash. */
|
||||||
|
+
|
||||||
|
+ /* This is expected to succeed. */
|
||||||
|
+ puts ("info: loading tst-dlopenfailmod2.so");
|
||||||
|
+ void *handle = xdlopen ("tst-dlopenfailmod2.so", RTLD_NOW);
|
||||||
|
+ xdlclose (handle);
|
||||||
|
+
|
||||||
|
+ /* libpthread should remain loaded. */
|
||||||
|
+ TEST_VERIFY (dlopen (LIBPTHREAD_SO, RTLD_LAZY | RTLD_NOLOAD) != NULL);
|
||||||
|
+ TEST_VERIFY (dlsym (NULL, "pthread_create") == NULL);
|
||||||
|
+
|
||||||
|
+ /* We can make libpthread global, and then the symbol should become
|
||||||
|
+ available. */
|
||||||
|
+ TEST_VERIFY (dlopen (LIBPTHREAD_SO, RTLD_LAZY | RTLD_GLOBAL) != NULL);
|
||||||
|
+ TEST_VERIFY (dlsym (NULL, "pthread_create") != NULL);
|
||||||
|
+
|
||||||
|
+ /* sem_open is sufficiently complex to depend on relocations. */
|
||||||
|
+ void *(*sem_open_ptr) (const char *, int flag, ...)
|
||||||
|
+ = dlsym (NULL, "sem_open");
|
||||||
|
+ if (sem_open_ptr == NULL)
|
||||||
|
+ /* Hurd does not implement sem_open. */
|
||||||
|
+ puts ("warning: sem_open not found, further testing not possible");
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ errno = 0;
|
||||||
|
+ TEST_VERIFY (sem_open_ptr ("/", 0) == NULL);
|
||||||
|
+ TEST_COMPARE (errno, EINVAL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-dlopenfaillinkmod.c b/elf/tst-dlopenfaillinkmod.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..3b14b02bc9a12c0b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-dlopenfaillinkmod.c
|
||||||
|
@@ -0,0 +1,17 @@
|
||||||
|
+/* Empty module with a soname which is not available at run time.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
diff --git a/elf/tst-dlopenfailmod1.c b/elf/tst-dlopenfailmod1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..6ef48829899a5a64
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-dlopenfailmod1.c
|
||||||
|
@@ -0,0 +1,36 @@
|
||||||
|
+/* Module which depends on two modules: one NODELETE, one missing.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+/* Note: Due to the missing second module, this object cannot be
|
||||||
|
+ loaded at run time. */
|
||||||
|
+
|
||||||
|
+#include <pthread.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+
|
||||||
|
+/* Force linking against libpthread. */
|
||||||
|
+void *pthread_create_reference = pthread_create;
|
||||||
|
+
|
||||||
|
+/* The constructor will never be executed because the module cannot be
|
||||||
|
+ loaded. */
|
||||||
|
+static void __attribute__ ((constructor))
|
||||||
|
+init (void)
|
||||||
|
+{
|
||||||
|
+ puts ("tst-dlopenfailmod1 constructor executed");
|
||||||
|
+ _exit (1);
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-dlopenfailmod2.c b/elf/tst-dlopenfailmod2.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..7d600386c13b98bd
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-dlopenfailmod2.c
|
||||||
|
@@ -0,0 +1,29 @@
|
||||||
|
+/* Module which depends on on a NODELETE module, and can be loaded.
|
||||||
|
+ Copyright (C) 2019 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 <pthread.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+
|
||||||
|
+/* Force linking against libpthread. */
|
||||||
|
+void *pthread_create_reference = pthread_create;
|
||||||
|
+
|
||||||
|
+static void __attribute__ ((constructor))
|
||||||
|
+init (void)
|
||||||
|
+{
|
||||||
|
+ puts ("info: tst-dlopenfailmod2.so constructor invoked");
|
||||||
|
+}
|
||||||
|
diff --git a/include/link.h b/include/link.h
|
||||||
|
index 83b1c34b7b4db8f3..a277b77cad6b52b1 100644
|
||||||
|
--- a/include/link.h
|
||||||
|
+++ b/include/link.h
|
||||||
|
@@ -79,6 +79,21 @@ struct r_search_path_struct
|
||||||
|
int malloced;
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* Type used by the l_nodelete member. */
|
||||||
|
+enum link_map_nodelete
|
||||||
|
+{
|
||||||
|
+ /* This link map can be deallocated. */
|
||||||
|
+ link_map_nodelete_inactive = 0, /* Zero-initialized in _dl_new_object. */
|
||||||
|
+
|
||||||
|
+ /* This link map cannot be deallocated. */
|
||||||
|
+ link_map_nodelete_active,
|
||||||
|
+
|
||||||
|
+ /* This link map cannot be deallocated after dlopen has succeded.
|
||||||
|
+ dlopen turns this into link_map_nodelete_active. dlclose treats
|
||||||
|
+ this intermediate state as link_map_nodelete_active. */
|
||||||
|
+ link_map_nodelete_pending,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
|
||||||
|
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
|
||||||
|
members form a chain of all the shared objects loaded at startup.
|
||||||
|
@@ -203,6 +218,11 @@ struct link_map
|
||||||
|
freed, ie. not allocated with
|
||||||
|
the dummy malloc in ld.so. */
|
||||||
|
|
||||||
|
+ /* Actually of type enum link_map_nodelete. Separate byte due to
|
||||||
|
+ a read in add_dependency in elf/dl-lookup.c outside the loader
|
||||||
|
+ lock. Only valid for l_type == lt_loaded. */
|
||||||
|
+ unsigned char l_nodelete;
|
||||||
|
+
|
||||||
|
#include <link_map.h>
|
||||||
|
|
||||||
|
/* Collected information about own RPATH directories. */
|
104
SOURCES/glibc-rh1410154-9.patch
Normal file
104
SOURCES/glibc-rh1410154-9.patch
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Oct 31 19:30:19 2019 +0100
|
||||||
|
|
||||||
|
Block signals during the initial part of dlopen
|
||||||
|
|
||||||
|
Lazy binding in a signal handler that interrupts a dlopen sees
|
||||||
|
intermediate dynamic linker state. This has likely been always
|
||||||
|
unsafe, but with the new pending NODELETE state, this is clearly
|
||||||
|
incorrect. Other threads are excluded via the loader lock, but the
|
||||||
|
current thread is not. Blocking signals until right before ELF
|
||||||
|
constructors run is the safe thing to do.
|
||||||
|
|
||||||
|
Change-Id: Iad079080ebe7442c13313ba11dc2797953faef35
|
||||||
|
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index 79c6e4c8ed1c9dfa..25838b073ac1edaf 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -34,6 +34,7 @@
|
||||||
|
#include <atomic.h>
|
||||||
|
#include <libc-internal.h>
|
||||||
|
#include <array_length.h>
|
||||||
|
+#include <internal-signals.h>
|
||||||
|
|
||||||
|
#include <dl-dst.h>
|
||||||
|
#include <dl-prop.h>
|
||||||
|
@@ -52,6 +53,10 @@ struct dl_open_args
|
||||||
|
/* Namespace ID. */
|
||||||
|
Lmid_t nsid;
|
||||||
|
|
||||||
|
+ /* Original signal mask. Used for unblocking signal handlers before
|
||||||
|
+ running ELF constructors. */
|
||||||
|
+ sigset_t original_signal_mask;
|
||||||
|
+
|
||||||
|
/* Original value of _ns_global_scope_pending_adds. Set by
|
||||||
|
dl_open_worker. Only valid if nsid is a real namespace
|
||||||
|
(non-negative). */
|
||||||
|
@@ -524,12 +529,16 @@ dl_open_worker (void *a)
|
||||||
|
if (new == NULL)
|
||||||
|
{
|
||||||
|
assert (mode & RTLD_NOLOAD);
|
||||||
|
+ __libc_signal_restore_set (&args->original_signal_mask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__glibc_unlikely (mode & __RTLD_SPROF))
|
||||||
|
- /* This happens only if we load a DSO for 'sprof'. */
|
||||||
|
- return;
|
||||||
|
+ {
|
||||||
|
+ /* This happens only if we load a DSO for 'sprof'. */
|
||||||
|
+ __libc_signal_restore_set (&args->original_signal_mask);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* This object is directly loaded. */
|
||||||
|
++new->l_direct_opencount;
|
||||||
|
@@ -565,6 +574,7 @@ dl_open_worker (void *a)
|
||||||
|
|
||||||
|
assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
|
||||||
|
|
||||||
|
+ __libc_signal_restore_set (&args->original_signal_mask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -745,6 +755,10 @@ dl_open_worker (void *a)
|
||||||
|
if (mode & RTLD_GLOBAL)
|
||||||
|
add_to_global_resize (new);
|
||||||
|
|
||||||
|
+ /* Unblock signals. Data structures are now consistent, and
|
||||||
|
+ application code may run. */
|
||||||
|
+ __libc_signal_restore_set (&args->original_signal_mask);
|
||||||
|
+
|
||||||
|
/* Run the initializer functions of new objects. Temporarily
|
||||||
|
disable the exception handler, so that lazy binding failures are
|
||||||
|
fatal. */
|
||||||
|
@@ -834,6 +848,10 @@ no more namespaces available for dlmopen()"));
|
||||||
|
args.argv = argv;
|
||||||
|
args.env = env;
|
||||||
|
|
||||||
|
+ /* Recursive lazy binding during manipulation of the dynamic loader
|
||||||
|
+ structures may result in incorrect behavior. */
|
||||||
|
+ __libc_signal_block_all (&args.original_signal_mask);
|
||||||
|
+
|
||||||
|
struct dl_exception exception;
|
||||||
|
int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
|
||||||
|
|
||||||
|
@@ -874,10 +892,16 @@ no more namespaces available for dlmopen()"));
|
||||||
|
|
||||||
|
_dl_close_worker (args.map, true);
|
||||||
|
|
||||||
|
+ /* Restore the signal mask. In the success case, this
|
||||||
|
+ happens inside dl_open_worker. */
|
||||||
|
+ __libc_signal_restore_set (&args.original_signal_mask);
|
||||||
|
+
|
||||||
|
/* All link_map_nodelete_pending objects should have been
|
||||||
|
deleted at this point, which is why it is not necessary
|
||||||
|
to reset the flag here. */
|
||||||
|
}
|
||||||
|
+ else
|
||||||
|
+ __libc_signal_restore_set (&args.original_signal_mask);
|
||||||
|
|
||||||
|
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
|
||||||
|
|
545
SOURCES/glibc-rh1682954.patch
Normal file
545
SOURCES/glibc-rh1682954.patch
Normal file
@ -0,0 +1,545 @@
|
|||||||
|
From 0d3905b110000463775b3fb189213833acaebf81 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||||
|
Date: Mon, 1 Jul 2019 12:23:10 -0700
|
||||||
|
Subject: Call _dl_open_check after relocation [BZ #24259]
|
||||||
|
|
||||||
|
This is a workaround for [BZ #20839] which doesn't remove the NODELETE
|
||||||
|
object when _dl_open_check throws an exception. Move it after relocation
|
||||||
|
in dl_open_worker to avoid leaving the NODELETE object mapped without
|
||||||
|
relocation.
|
||||||
|
|
||||||
|
[BZ #24259]
|
||||||
|
* elf/dl-open.c (dl_open_worker): Call _dl_open_check after
|
||||||
|
relocation.
|
||||||
|
* sysdeps/x86/Makefile (tests): Add tst-cet-legacy-5a,
|
||||||
|
tst-cet-legacy-5b, tst-cet-legacy-6a and tst-cet-legacy-6b.
|
||||||
|
(modules-names): Add tst-cet-legacy-mod-5a, tst-cet-legacy-mod-5b,
|
||||||
|
tst-cet-legacy-mod-5c, tst-cet-legacy-mod-6a, tst-cet-legacy-mod-6b
|
||||||
|
and tst-cet-legacy-mod-6c.
|
||||||
|
(CFLAGS-tst-cet-legacy-5a.c): New.
|
||||||
|
(CFLAGS-tst-cet-legacy-5b.c): Likewise.
|
||||||
|
(CFLAGS-tst-cet-legacy-mod-5a.c): Likewise.
|
||||||
|
(CFLAGS-tst-cet-legacy-mod-5b.c): Likewise.
|
||||||
|
(CFLAGS-tst-cet-legacy-mod-5c.c): Likewise.
|
||||||
|
(CFLAGS-tst-cet-legacy-6a.c): Likewise.
|
||||||
|
(CFLAGS-tst-cet-legacy-6b.c): Likewise.
|
||||||
|
(CFLAGS-tst-cet-legacy-mod-6a.c): Likewise.
|
||||||
|
(CFLAGS-tst-cet-legacy-mod-6b.c): Likewise.
|
||||||
|
(CFLAGS-tst-cet-legacy-mod-6c.c): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-5a): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-5a.out): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-mod-5a.so): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-mod-5b.so): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-5b): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-5b.out): Likewise.
|
||||||
|
(tst-cet-legacy-5b-ENV): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-6a): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-6a.out): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-mod-6a.so): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-mod-6b.so): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-6b): Likewise.
|
||||||
|
($(objpfx)tst-cet-legacy-6b.out): Likewise.
|
||||||
|
(tst-cet-legacy-6b-ENV): Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-5.c: New file.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-5a.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-5b.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-6.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-6a.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-6b.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-mod-5.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-mod-5a.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-mod-5b.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-mod-5c.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-mod-6.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-mod-6a.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-mod-6b.c: Likewise.
|
||||||
|
* sysdeps/x86/tst-cet-legacy-mod-6c.c: Likewise.
|
||||||
|
|
||||||
|
(cherry picked from commit d0093c5cefb7f7a4143f3bb03743633823229cc6)
|
||||||
|
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index f6c8ef1043..518a6cad69 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -292,8 +292,6 @@ dl_open_worker (void *a)
|
||||||
|
_dl_debug_state ();
|
||||||
|
LIBC_PROBE (map_complete, 3, args->nsid, r, new);
|
||||||
|
|
||||||
|
- _dl_open_check (new);
|
||||||
|
-
|
||||||
|
/* Print scope information. */
|
||||||
|
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
|
||||||
|
_dl_show_scope (new, 0);
|
||||||
|
@@ -366,6 +364,12 @@ dl_open_worker (void *a)
|
||||||
|
_dl_relocate_object (l, l->l_scope, reloc_mode, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* NB: Workaround for [BZ #20839] which doesn't remove the NODELETE
|
||||||
|
+ object when _dl_open_check throws an exception. Move it after
|
||||||
|
+ relocation to avoid leaving the NODELETE object mapped without
|
||||||
|
+ relocation. */
|
||||||
|
+ _dl_open_check (new);
|
||||||
|
+
|
||||||
|
/* If the file is not loaded now as a dependency, add the search
|
||||||
|
list of the newly loaded object to the scope. */
|
||||||
|
bool any_tls = false;
|
||||||
|
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||||||
|
index 337b0b63dc..43ad4a79ff 100644
|
||||||
|
--- a/sysdeps/x86/Makefile
|
||||||
|
+++ b/sysdeps/x86/Makefile
|
||||||
|
@@ -19,12 +19,17 @@ ifeq ($(subdir),elf)
|
||||||
|
sysdep-dl-routines += dl-cet
|
||||||
|
|
||||||
|
tests += tst-cet-legacy-1 tst-cet-legacy-2 tst-cet-legacy-2a \
|
||||||
|
- tst-cet-legacy-3 tst-cet-legacy-4
|
||||||
|
+ tst-cet-legacy-3 tst-cet-legacy-4 \
|
||||||
|
+ tst-cet-legacy-5a tst-cet-legacy-6a
|
||||||
|
ifneq (no,$(have-tunables))
|
||||||
|
-tests += tst-cet-legacy-4a tst-cet-legacy-4b tst-cet-legacy-4c
|
||||||
|
+tests += tst-cet-legacy-4a tst-cet-legacy-4b tst-cet-legacy-4c \
|
||||||
|
+ tst-cet-legacy-5b tst-cet-legacy-6b
|
||||||
|
endif
|
||||||
|
modules-names += tst-cet-legacy-mod-1 tst-cet-legacy-mod-2 \
|
||||||
|
- tst-cet-legacy-mod-4
|
||||||
|
+ tst-cet-legacy-mod-4 tst-cet-legacy-mod-5a \
|
||||||
|
+ tst-cet-legacy-mod-5b tst-cet-legacy-mod-5c \
|
||||||
|
+ tst-cet-legacy-mod-6a tst-cet-legacy-mod-6b \
|
||||||
|
+ tst-cet-legacy-mod-6c
|
||||||
|
|
||||||
|
CFLAGS-tst-cet-legacy-2.c += -fcf-protection=branch
|
||||||
|
CFLAGS-tst-cet-legacy-2a.c += -fcf-protection
|
||||||
|
@@ -35,6 +40,16 @@ CFLAGS-tst-cet-legacy-4.c += -fcf-protection=branch
|
||||||
|
CFLAGS-tst-cet-legacy-4a.c += -fcf-protection
|
||||||
|
CFLAGS-tst-cet-legacy-4b.c += -fcf-protection
|
||||||
|
CFLAGS-tst-cet-legacy-mod-4.c += -fcf-protection=none
|
||||||
|
+CFLAGS-tst-cet-legacy-5a.c += -fcf-protection
|
||||||
|
+CFLAGS-tst-cet-legacy-5b.c += -fcf-protection
|
||||||
|
+CFLAGS-tst-cet-legacy-mod-5a.c += -fcf-protection=none
|
||||||
|
+CFLAGS-tst-cet-legacy-mod-5b.c += -fcf-protection
|
||||||
|
+CFLAGS-tst-cet-legacy-mod-5c.c += -fcf-protection
|
||||||
|
+CFLAGS-tst-cet-legacy-6a.c += -fcf-protection
|
||||||
|
+CFLAGS-tst-cet-legacy-6b.c += -fcf-protection
|
||||||
|
+CFLAGS-tst-cet-legacy-mod-6a.c += -fcf-protection=none
|
||||||
|
+CFLAGS-tst-cet-legacy-mod-6b.c += -fcf-protection
|
||||||
|
+CFLAGS-tst-cet-legacy-mod-6c.c += -fcf-protection
|
||||||
|
|
||||||
|
$(objpfx)tst-cet-legacy-1: $(objpfx)tst-cet-legacy-mod-1.so \
|
||||||
|
$(objpfx)tst-cet-legacy-mod-2.so
|
||||||
|
@@ -44,6 +59,17 @@ $(objpfx)tst-cet-legacy-2a: $(objpfx)tst-cet-legacy-mod-2.so $(libdl)
|
||||||
|
$(objpfx)tst-cet-legacy-2a.out: $(objpfx)tst-cet-legacy-mod-1.so
|
||||||
|
$(objpfx)tst-cet-legacy-4: $(libdl)
|
||||||
|
$(objpfx)tst-cet-legacy-4.out: $(objpfx)tst-cet-legacy-mod-4.so
|
||||||
|
+$(objpfx)tst-cet-legacy-5a: $(libdl)
|
||||||
|
+$(objpfx)tst-cet-legacy-5a.out: $(objpfx)tst-cet-legacy-mod-5a.so \
|
||||||
|
+ $(objpfx)tst-cet-legacy-mod-5b.so
|
||||||
|
+$(objpfx)tst-cet-legacy-mod-5a.so: $(objpfx)tst-cet-legacy-mod-5c.so
|
||||||
|
+$(objpfx)tst-cet-legacy-mod-5b.so: $(objpfx)tst-cet-legacy-mod-5c.so
|
||||||
|
+$(objpfx)tst-cet-legacy-6a: $(libdl)
|
||||||
|
+$(objpfx)tst-cet-legacy-6a.out: $(objpfx)tst-cet-legacy-mod-6a.so \
|
||||||
|
+ $(objpfx)tst-cet-legacy-mod-6b.so
|
||||||
|
+$(objpfx)tst-cet-legacy-mod-6a.so: $(objpfx)tst-cet-legacy-mod-6c.so
|
||||||
|
+$(objpfx)tst-cet-legacy-mod-6b.so: $(objpfx)tst-cet-legacy-mod-6c.so
|
||||||
|
+LDFLAGS-tst-cet-legacy-mod-6c.so = -Wl,--enable-new-dtags,-z,nodelete
|
||||||
|
ifneq (no,$(have-tunables))
|
||||||
|
$(objpfx)tst-cet-legacy-4a: $(libdl)
|
||||||
|
$(objpfx)tst-cet-legacy-4a.out: $(objpfx)tst-cet-legacy-mod-4.so
|
||||||
|
@@ -54,6 +80,14 @@ tst-cet-legacy-4b-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=on
|
||||||
|
$(objpfx)tst-cet-legacy-4c: $(libdl)
|
||||||
|
$(objpfx)tst-cet-legacy-4c.out: $(objpfx)tst-cet-legacy-mod-4.so
|
||||||
|
tst-cet-legacy-4c-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=off
|
||||||
|
+$(objpfx)tst-cet-legacy-5b: $(libdl)
|
||||||
|
+$(objpfx)tst-cet-legacy-5b.out: $(objpfx)tst-cet-legacy-mod-5a.so \
|
||||||
|
+ $(objpfx)tst-cet-legacy-mod-5b.so
|
||||||
|
+tst-cet-legacy-5b-ENV = GLIBC_TUNABLES=glibc.tune.x86_ibt=off:glibc.tune.x86_shstk=off
|
||||||
|
+$(objpfx)tst-cet-legacy-6b: $(libdl)
|
||||||
|
+$(objpfx)tst-cet-legacy-6b.out: $(objpfx)tst-cet-legacy-mod-6a.so \
|
||||||
|
+ $(objpfx)tst-cet-legacy-mod-6b.so
|
||||||
|
+tst-cet-legacy-6b-ENV = GLIBC_TUNABLES=glibc.tune.x86_ibt=off:glibc.tune.x86_shstk=off
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-5.c b/sysdeps/x86/tst-cet-legacy-5.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..fbf640f664
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-5.c
|
||||||
|
@@ -0,0 +1,76 @@
|
||||||
|
+/* Check compatibility of CET-enabled executable with dlopened legacy
|
||||||
|
+ shared object.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <dlfcn.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+do_test_1 (const char *modname, bool fail)
|
||||||
|
+{
|
||||||
|
+ int (*fp) (void);
|
||||||
|
+ void *h;
|
||||||
|
+
|
||||||
|
+ h = dlopen (modname, RTLD_LAZY);
|
||||||
|
+ if (h == NULL)
|
||||||
|
+ {
|
||||||
|
+ if (fail)
|
||||||
|
+ {
|
||||||
|
+ const char *err = dlerror ();
|
||||||
|
+ if (strstr (err, "shadow stack isn't enabled") == NULL)
|
||||||
|
+ {
|
||||||
|
+ printf ("incorrect dlopen '%s' error: %s\n", modname,
|
||||||
|
+ dlerror ());
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ printf ("cannot open '%s': %s\n", modname, dlerror ());
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fp = dlsym (h, "test");
|
||||||
|
+ if (fp == NULL)
|
||||||
|
+ {
|
||||||
|
+ printf ("cannot get symbol 'test': %s\n", dlerror ());
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (fp () != 0)
|
||||||
|
+ {
|
||||||
|
+ puts ("test () != 0");
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dlclose (h);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ do_test_1 ("tst-cet-legacy-mod-5a.so", true);
|
||||||
|
+ do_test_1 ("tst-cet-legacy-mod-5b.so", false);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-5a.c b/sysdeps/x86/tst-cet-legacy-5a.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..fc5a609dff
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-5a.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-cet-legacy-5.c"
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-5b.c b/sysdeps/x86/tst-cet-legacy-5b.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..fc5a609dff
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-5b.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-cet-legacy-5.c"
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-6.c b/sysdeps/x86/tst-cet-legacy-6.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..9151225264
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-6.c
|
||||||
|
@@ -0,0 +1,76 @@
|
||||||
|
+/* Check compatibility of CET-enabled executable with dlopened legacy
|
||||||
|
+ shared object.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <dlfcn.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+do_test_1 (const char *modname, bool fail)
|
||||||
|
+{
|
||||||
|
+ int (*fp) (void);
|
||||||
|
+ void *h;
|
||||||
|
+
|
||||||
|
+ h = dlopen (modname, RTLD_LAZY);
|
||||||
|
+ if (h == NULL)
|
||||||
|
+ {
|
||||||
|
+ if (fail)
|
||||||
|
+ {
|
||||||
|
+ const char *err = dlerror ();
|
||||||
|
+ if (strstr (err, "shadow stack isn't enabled") == NULL)
|
||||||
|
+ {
|
||||||
|
+ printf ("incorrect dlopen '%s' error: %s\n", modname,
|
||||||
|
+ dlerror ());
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ printf ("cannot open '%s': %s\n", modname, dlerror ());
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fp = dlsym (h, "test");
|
||||||
|
+ if (fp == NULL)
|
||||||
|
+ {
|
||||||
|
+ printf ("cannot get symbol 'test': %s\n", dlerror ());
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (fp () != 0)
|
||||||
|
+ {
|
||||||
|
+ puts ("test () != 0");
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dlclose (h);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ do_test_1 ("tst-cet-legacy-mod-6a.so", true);
|
||||||
|
+ do_test_1 ("tst-cet-legacy-mod-6b.so", false);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-6a.c b/sysdeps/x86/tst-cet-legacy-6a.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..2d1546d36b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-6a.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-cet-legacy-6.c"
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-6b.c b/sysdeps/x86/tst-cet-legacy-6b.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..2d1546d36b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-6b.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-cet-legacy-6.c"
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-mod-5.c b/sysdeps/x86/tst-cet-legacy-mod-5.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..3c1071c2ef
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-mod-5.c
|
||||||
|
@@ -0,0 +1,31 @@
|
||||||
|
+/* Check compatibility of CET-enabled executable with dlopened legacy
|
||||||
|
+ shared object.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <error.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+extern void foo (void);
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+test (void)
|
||||||
|
+{
|
||||||
|
+ foo ();
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-mod-5a.c b/sysdeps/x86/tst-cet-legacy-mod-5a.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..daa43e4e8d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-mod-5a.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-cet-legacy-mod-5.c"
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-mod-5b.c b/sysdeps/x86/tst-cet-legacy-mod-5b.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..daa43e4e8d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-mod-5b.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-cet-legacy-mod-5.c"
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-mod-5c.c b/sysdeps/x86/tst-cet-legacy-mod-5c.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..e529a42ac0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-mod-5c.c
|
||||||
|
@@ -0,0 +1,36 @@
|
||||||
|
+/* Check compatibility of CET-enabled executable with dlopened legacy
|
||||||
|
+ shared object.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+static int called = 0;
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+__attribute__ ((constructor))
|
||||||
|
+init (void)
|
||||||
|
+{
|
||||||
|
+ called = 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+foo (void)
|
||||||
|
+{
|
||||||
|
+ if (!called)
|
||||||
|
+ abort ();
|
||||||
|
+}
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-mod-6.c b/sysdeps/x86/tst-cet-legacy-mod-6.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..3c1071c2ef
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-mod-6.c
|
||||||
|
@@ -0,0 +1,31 @@
|
||||||
|
+/* Check compatibility of CET-enabled executable with dlopened legacy
|
||||||
|
+ shared object.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <error.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+extern void foo (void);
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+test (void)
|
||||||
|
+{
|
||||||
|
+ foo ();
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-mod-6a.c b/sysdeps/x86/tst-cet-legacy-mod-6a.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..c89b8fe8ff
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-mod-6a.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-cet-legacy-mod-6.c"
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-mod-6b.c b/sysdeps/x86/tst-cet-legacy-mod-6b.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..c89b8fe8ff
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-mod-6b.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-cet-legacy-mod-6.c"
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-mod-6c.c b/sysdeps/x86/tst-cet-legacy-mod-6c.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..e529a42ac0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-mod-6c.c
|
||||||
|
@@ -0,0 +1,36 @@
|
||||||
|
+/* Check compatibility of CET-enabled executable with dlopened legacy
|
||||||
|
+ shared object.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+static int called = 0;
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+__attribute__ ((constructor))
|
||||||
|
+init (void)
|
||||||
|
+{
|
||||||
|
+ called = 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+foo (void)
|
||||||
|
+{
|
||||||
|
+ if (!called)
|
||||||
|
+ abort ();
|
||||||
|
+}
|
||||||
|
diff --git a/sysdeps/x86/tst-cet-legacy-mod-6d.c b/sysdeps/x86/tst-cet-legacy-mod-6d.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..eb233a1d10
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/tst-cet-legacy-mod-6d.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-cet-legacy-mod-6c.c"
|
35
SOURCES/glibc-rh1726638-1.patch
Normal file
35
SOURCES/glibc-rh1726638-1.patch
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
commit 55f82d328d2dd1c7c13c1992f4b9bf9c95b57551
|
||||||
|
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||||
|
Date: Thu Apr 25 15:35:35 2019 +0100
|
||||||
|
|
||||||
|
aarch64: add STO_AARCH64_VARIANT_PCS and DT_AARCH64_VARIANT_PCS
|
||||||
|
|
||||||
|
STO_AARCH64_VARIANT_PCS is a non-visibility st_other flag for marking
|
||||||
|
symbols that reference functions that may follow a variant PCS with
|
||||||
|
different register usage convention from the base PCS.
|
||||||
|
|
||||||
|
DT_AARCH64_VARIANT_PCS is a dynamic tag that marks ELF modules that
|
||||||
|
have R_*_JUMP_SLOT relocations for symbols marked with
|
||||||
|
STO_AARCH64_VARIANT_PCS (i.e. have variant PCS calls via a PLT).
|
||||||
|
|
||||||
|
* elf/elf.h (STO_AARCH64_VARIANT_PCS): Define.
|
||||||
|
(DT_AARCH64_VARIANT_PCS): Define.
|
||||||
|
|
||||||
|
diff --git a/elf/elf.h b/elf/elf.h
|
||||||
|
index 7e2b072a7f75451c..74f7f479ce817040 100644
|
||||||
|
--- a/elf/elf.h
|
||||||
|
+++ b/elf/elf.h
|
||||||
|
@@ -2847,6 +2847,13 @@ enum
|
||||||
|
#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */
|
||||||
|
#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
|
||||||
|
|
||||||
|
+/* AArch64 specific values for the Dyn d_tag field. */
|
||||||
|
+#define DT_AARCH64_VARIANT_PCS (DT_LOPROC + 5)
|
||||||
|
+#define DT_AARCH64_NUM 6
|
||||||
|
+
|
||||||
|
+/* AArch64 specific values for the st_other field. */
|
||||||
|
+#define STO_AARCH64_VARIANT_PCS 0x80
|
||||||
|
+
|
||||||
|
/* ARM relocs. */
|
||||||
|
|
||||||
|
#define R_ARM_NONE 0 /* No reloc */
|
138
SOURCES/glibc-rh1726638-2.patch
Normal file
138
SOURCES/glibc-rh1726638-2.patch
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
commit 82bc69c012838a381c4167c156a06f4598f34227
|
||||||
|
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||||
|
Date: Thu Apr 25 15:35:35 2019 +0100
|
||||||
|
|
||||||
|
aarch64: handle STO_AARCH64_VARIANT_PCS
|
||||||
|
|
||||||
|
Avoid lazy binding of symbols that may follow a variant PCS with different
|
||||||
|
register usage convention from the base PCS.
|
||||||
|
|
||||||
|
Currently the lazy binding entry code does not preserve all the registers
|
||||||
|
required for AdvSIMD and SVE vector calls. Saving and restoring all
|
||||||
|
registers unconditionally may break existing binaries, even if they never
|
||||||
|
use vector calls, because of the larger stack requirement for lazy
|
||||||
|
resolution, which can be significant on an SVE system.
|
||||||
|
|
||||||
|
The solution is to mark all symbols in the symbol table that may follow
|
||||||
|
a variant PCS so the dynamic linker can handle them specially. In this
|
||||||
|
patch such symbols are always resolved at load time, not lazily.
|
||||||
|
|
||||||
|
So currently LD_AUDIT for variant PCS symbols are not supported, for that
|
||||||
|
the _dl_runtime_profile entry needs to be changed e.g. to unconditionally
|
||||||
|
save/restore all registers (but pass down arg and retval registers to
|
||||||
|
pltentry/exit callbacks according to the base PCS).
|
||||||
|
|
||||||
|
This patch also removes a __builtin_expect from the modified code because
|
||||||
|
the branch prediction hint did not seem useful.
|
||||||
|
|
||||||
|
* sysdeps/aarch64/dl-dtprocnum.h: New file.
|
||||||
|
* sysdeps/aarch64/dl-machine.h (DT_AARCH64): Define.
|
||||||
|
(elf_machine_runtime_setup): Handle DT_AARCH64_VARIANT_PCS.
|
||||||
|
(elf_machine_lazy_rel): Check STO_AARCH64_VARIANT_PCS and bind such
|
||||||
|
symbols at load time.
|
||||||
|
* sysdeps/aarch64/linkmap.h (struct link_map_machine): Add variant_pcs.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/aarch64/dl-dtprocnum.h b/sysdeps/aarch64/dl-dtprocnum.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..4ac2adf23458e02d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/aarch64/dl-dtprocnum.h
|
||||||
|
@@ -0,0 +1,21 @@
|
||||||
|
+/* Configuration of lookup functions. AArch64 version.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library. If not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* Number of extra dynamic section entries for this architecture. By
|
||||||
|
+ default there are none. */
|
||||||
|
+#define DT_THISPROCNUM DT_AARCH64_NUM
|
||||||
|
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
|
||||||
|
index 4935aa7c543876db..d4494852b32b8783 100644
|
||||||
|
--- a/sysdeps/aarch64/dl-machine.h
|
||||||
|
+++ b/sysdeps/aarch64/dl-machine.h
|
||||||
|
@@ -27,6 +27,9 @@
|
||||||
|
#include <dl-irel.h>
|
||||||
|
#include <cpu-features.c>
|
||||||
|
|
||||||
|
+/* Translate a processor specific dynamic tag to the index in l_info array. */
|
||||||
|
+#define DT_AARCH64(x) (DT_AARCH64_##x - DT_LOPROC + DT_NUM)
|
||||||
|
+
|
||||||
|
/* Return nonzero iff ELF header is compatible with the running host. */
|
||||||
|
static inline int __attribute__ ((unused))
|
||||||
|
elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
|
||||||
|
@@ -102,6 +105,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Check if STO_AARCH64_VARIANT_PCS needs to be handled. */
|
||||||
|
+ if (l->l_info[DT_AARCH64 (VARIANT_PCS)])
|
||||||
|
+ l->l_mach.variant_pcs = 1;
|
||||||
|
+
|
||||||
|
return lazy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -388,10 +395,37 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||||
|
/* Check for unexpected PLT reloc type. */
|
||||||
|
if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1))
|
||||||
|
{
|
||||||
|
- if (__builtin_expect (map->l_mach.plt, 0) == 0)
|
||||||
|
- *reloc_addr += l_addr;
|
||||||
|
- else
|
||||||
|
- *reloc_addr = map->l_mach.plt;
|
||||||
|
+ if (map->l_mach.plt == 0)
|
||||||
|
+ {
|
||||||
|
+ /* Prelinking. */
|
||||||
|
+ *reloc_addr += l_addr;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (__glibc_unlikely (map->l_mach.variant_pcs))
|
||||||
|
+ {
|
||||||
|
+ /* Check the symbol table for variant PCS symbols. */
|
||||||
|
+ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
|
||||||
|
+ const ElfW (Sym) *symtab =
|
||||||
|
+ (const void *)D_PTR (map, l_info[DT_SYMTAB]);
|
||||||
|
+ const ElfW (Sym) *sym = &symtab[symndx];
|
||||||
|
+ if (__glibc_unlikely (sym->st_other & STO_AARCH64_VARIANT_PCS))
|
||||||
|
+ {
|
||||||
|
+ /* Avoid lazy resolution of variant PCS symbols. */
|
||||||
|
+ const struct r_found_version *version = NULL;
|
||||||
|
+ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||||
|
+ {
|
||||||
|
+ const ElfW (Half) *vernum =
|
||||||
|
+ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||||
|
+ version = &map->l_versions[vernum[symndx] & 0x7fff];
|
||||||
|
+ }
|
||||||
|
+ elf_machine_rela (map, reloc, sym, version, reloc_addr,
|
||||||
|
+ skip_ifunc);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *reloc_addr = map->l_mach.plt;
|
||||||
|
}
|
||||||
|
else if (__builtin_expect (r_type == AARCH64_R(TLSDESC), 1))
|
||||||
|
{
|
||||||
|
diff --git a/sysdeps/aarch64/linkmap.h b/sysdeps/aarch64/linkmap.h
|
||||||
|
index 6852f343a1efd150..dd8597470c3d2174 100644
|
||||||
|
--- a/sysdeps/aarch64/linkmap.h
|
||||||
|
+++ b/sysdeps/aarch64/linkmap.h
|
||||||
|
@@ -20,4 +20,5 @@ struct link_map_machine
|
||||||
|
{
|
||||||
|
ElfW(Addr) plt; /* Address of .plt */
|
||||||
|
void *tlsdesc_table; /* Address of TLS descriptor hash table. */
|
||||||
|
+ int variant_pcs; /* If set, PLT calls may follow a variant PCS. */
|
||||||
|
};
|
49
SOURCES/glibc-rh1726638-3.patch
Normal file
49
SOURCES/glibc-rh1726638-3.patch
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
commit 30ba0375464f34e4bf8129f3d3dc14d0c09add17
|
||||||
|
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||||
|
Date: Tue Jul 9 12:11:39 2019 +0100
|
||||||
|
|
||||||
|
aarch64: simplify the DT_AARCH64_VARIANT_PCS handling code
|
||||||
|
|
||||||
|
Remove unnecessary variant_pcs field: the dynamic tag can be checked
|
||||||
|
directly.
|
||||||
|
|
||||||
|
* sysdeps/aarch64/dl-machine.h (elf_machine_runtime_setup): Remove the
|
||||||
|
DT_AARCH64_VARIANT_PCS check.
|
||||||
|
(elf_machine_lazy_rel): Use l_info[DT_AARCH64 (VARIANT_PCS)].
|
||||||
|
* sysdeps/aarch64/linkmap.h (struct link_map_machine): Remove
|
||||||
|
variant_pcs.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
|
||||||
|
index d4494852b32b8783..b39eae4acf4086ee 100644
|
||||||
|
--- a/sysdeps/aarch64/dl-machine.h
|
||||||
|
+++ b/sysdeps/aarch64/dl-machine.h
|
||||||
|
@@ -105,10 +105,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Check if STO_AARCH64_VARIANT_PCS needs to be handled. */
|
||||||
|
- if (l->l_info[DT_AARCH64 (VARIANT_PCS)])
|
||||||
|
- l->l_mach.variant_pcs = 1;
|
||||||
|
-
|
||||||
|
return lazy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -402,7 +398,7 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (__glibc_unlikely (map->l_mach.variant_pcs))
|
||||||
|
+ if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL))
|
||||||
|
{
|
||||||
|
/* Check the symbol table for variant PCS symbols. */
|
||||||
|
const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
|
||||||
|
diff --git a/sysdeps/aarch64/linkmap.h b/sysdeps/aarch64/linkmap.h
|
||||||
|
index dd8597470c3d2174..6852f343a1efd150 100644
|
||||||
|
--- a/sysdeps/aarch64/linkmap.h
|
||||||
|
+++ b/sysdeps/aarch64/linkmap.h
|
||||||
|
@@ -20,5 +20,4 @@ struct link_map_machine
|
||||||
|
{
|
||||||
|
ElfW(Addr) plt; /* Address of .plt */
|
||||||
|
void *tlsdesc_table; /* Address of TLS descriptor hash table. */
|
||||||
|
- int variant_pcs; /* If set, PLT calls may follow a variant PCS. */
|
||||||
|
};
|
25
SOURCES/glibc-rh1735747-1.patch
Normal file
25
SOURCES/glibc-rh1735747-1.patch
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
commit 6d750b18999b52ec74102c046cd27181f943bda8
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Aug 1 14:06:24 2019 +0200
|
||||||
|
|
||||||
|
malloc: Remove unwanted leading whitespace in malloc_info [BZ #24867]
|
||||||
|
|
||||||
|
It was introduced in commit 6c8dbf00f536d78b1937b5af6f57be47fd376344
|
||||||
|
("Reformat malloc to gnu style.").
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
(cherry picked from commit b0f6679bcd738ea244a14acd879d974901e56c8e)
|
||||||
|
|
||||||
|
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||||
|
index e6a483d5cf7c4312..4fc7f175fe42d6c6 100644
|
||||||
|
--- a/malloc/malloc.c
|
||||||
|
+++ b/malloc/malloc.c
|
||||||
|
@@ -5518,7 +5518,7 @@ __malloc_info (int options, FILE *fp)
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nsizes; ++i)
|
||||||
|
if (sizes[i].count != 0 && i != NFASTBINS)
|
||||||
|
- fprintf (fp, " \
|
||||||
|
+ fprintf (fp, "\
|
||||||
|
<size from=\"%zu\" to=\"%zu\" total=\"%zu\" count=\"%zu\"/>\n",
|
||||||
|
sizes[i].from, sizes[i].to, sizes[i].total, sizes[i].count);
|
||||||
|
|
35
SOURCES/glibc-rh1735747-2.patch
Normal file
35
SOURCES/glibc-rh1735747-2.patch
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
commit 91d5989356325759503311df67e750b358ef4148
|
||||||
|
Author: Niklas Hambüchen <mail@nh2.me>
|
||||||
|
Date: Thu Aug 8 22:02:27 2019 +0200
|
||||||
|
|
||||||
|
malloc: Fix missing accounting of top chunk in malloc_info [BZ #24026]
|
||||||
|
|
||||||
|
Fixes `<total type="rest" size="..."> incorrectly showing as 0 most
|
||||||
|
of the time.
|
||||||
|
|
||||||
|
The rest value being wrong is significant because to compute the
|
||||||
|
actual amount of memory handed out via malloc, the user must subtract
|
||||||
|
it from <system type="current" size="...">. That result being wrong
|
||||||
|
makes investigating memory fragmentation issues like
|
||||||
|
<https://bugzilla.redhat.com/show_bug.cgi?id=843478> close to
|
||||||
|
impossible.
|
||||||
|
|
||||||
|
(cherry picked from commit b6d2c4475d5abc05dd009575b90556bdd3c78ad0)
|
||||||
|
|
||||||
|
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||||
|
index 4fc7f175fe42d6c6..fcf480acdaea1b86 100644
|
||||||
|
--- a/malloc/malloc.c
|
||||||
|
+++ b/malloc/malloc.c
|
||||||
|
@@ -5433,6 +5433,12 @@ __malloc_info (int options, FILE *fp)
|
||||||
|
|
||||||
|
__libc_lock_lock (ar_ptr->mutex);
|
||||||
|
|
||||||
|
+ /* Account for top chunk. The top-most available chunk is
|
||||||
|
+ treated specially and is never in any bin. See "initial_top"
|
||||||
|
+ comments. */
|
||||||
|
+ avail = chunksize (ar_ptr->top);
|
||||||
|
+ nblocks = 1; /* Top always exists. */
|
||||||
|
+
|
||||||
|
for (size_t i = 0; i < NFASTBINS; ++i)
|
||||||
|
{
|
||||||
|
mchunkptr p = fastbin (ar_ptr, i);
|
117
SOURCES/glibc-rh1746928.patch
Normal file
117
SOURCES/glibc-rh1746928.patch
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
commit 669ff911e2571f74a2668493e326ac9a505776bd
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Feb 8 12:46:19 2019 +0100
|
||||||
|
|
||||||
|
nptl: Avoid fork handler lock for async-signal-safe fork [BZ #24161]
|
||||||
|
|
||||||
|
Commit 27761a1042daf01987e7d79636d0c41511c6df3c ("Refactor atfork
|
||||||
|
handlers") introduced a lock, atfork_lock, around fork handler list
|
||||||
|
accesses. It turns out that this lock occasionally results in
|
||||||
|
self-deadlocks in malloc/tst-mallocfork2:
|
||||||
|
|
||||||
|
(gdb) bt
|
||||||
|
#0 __lll_lock_wait_private ()
|
||||||
|
at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:63
|
||||||
|
#1 0x00007f160c6f927a in __run_fork_handlers (who=(unknown: 209394016),
|
||||||
|
who@entry=atfork_run_prepare) at register-atfork.c:116
|
||||||
|
#2 0x00007f160c6b7897 in __libc_fork () at ../sysdeps/nptl/fork.c:58
|
||||||
|
#3 0x00000000004027d6 in sigusr1_handler (signo=<optimized out>)
|
||||||
|
at tst-mallocfork2.c:80
|
||||||
|
#4 sigusr1_handler (signo=<optimized out>) at tst-mallocfork2.c:64
|
||||||
|
#5 <signal handler called>
|
||||||
|
#6 0x00007f160c6f92e4 in __run_fork_handlers (who=who@entry=atfork_run_parent)
|
||||||
|
at register-atfork.c:136
|
||||||
|
#7 0x00007f160c6b79a2 in __libc_fork () at ../sysdeps/nptl/fork.c:152
|
||||||
|
#8 0x0000000000402567 in do_test () at tst-mallocfork2.c:156
|
||||||
|
#9 0x0000000000402dd2 in support_test_main (argc=1, argv=0x7ffc81ef1ab0,
|
||||||
|
config=config@entry=0x7ffc81ef1970) at support_test_main.c:350
|
||||||
|
#10 0x0000000000402362 in main (argc=<optimized out>, argv=<optimized out>)
|
||||||
|
at ../support/test-driver.c:168
|
||||||
|
|
||||||
|
If no locking happens in the single-threaded case (where fork is
|
||||||
|
expected to be async-signal-safe), this deadlock is avoided.
|
||||||
|
(pthread_atfork is not required to be async-signal-safe, so a fork
|
||||||
|
call from a signal handler interrupting pthread_atfork is not
|
||||||
|
a problem.)
|
||||||
|
|
||||||
|
diff --git a/nptl/register-atfork.c b/nptl/register-atfork.c
|
||||||
|
index bc797b7..80a1bec 100644
|
||||||
|
--- a/nptl/register-atfork.c
|
||||||
|
+++ b/nptl/register-atfork.c
|
||||||
|
@@ -107,13 +107,14 @@ __unregister_atfork (void *dso_handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
-__run_fork_handlers (enum __run_fork_handler_type who)
|
||||||
|
+__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking)
|
||||||
|
{
|
||||||
|
struct fork_handler *runp;
|
||||||
|
|
||||||
|
if (who == atfork_run_prepare)
|
||||||
|
{
|
||||||
|
- lll_lock (atfork_lock, LLL_PRIVATE);
|
||||||
|
+ if (do_locking)
|
||||||
|
+ lll_lock (atfork_lock, LLL_PRIVATE);
|
||||||
|
size_t sl = fork_handler_list_size (&fork_handlers);
|
||||||
|
for (size_t i = sl; i > 0; i--)
|
||||||
|
{
|
||||||
|
@@ -133,7 +134,8 @@ __run_fork_handlers (enum __run_fork_handler_type who)
|
||||||
|
else if (who == atfork_run_parent && runp->parent_handler)
|
||||||
|
runp->parent_handler ();
|
||||||
|
}
|
||||||
|
- lll_unlock (atfork_lock, LLL_PRIVATE);
|
||||||
|
+ if (do_locking)
|
||||||
|
+ lll_unlock (atfork_lock, LLL_PRIVATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
|
||||||
|
index bd68f18..14b69a6 100644
|
||||||
|
--- a/sysdeps/nptl/fork.c
|
||||||
|
+++ b/sysdeps/nptl/fork.c
|
||||||
|
@@ -55,7 +55,7 @@ __libc_fork (void)
|
||||||
|
but our current fork implementation is not. */
|
||||||
|
bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads);
|
||||||
|
|
||||||
|
- __run_fork_handlers (atfork_run_prepare);
|
||||||
|
+ __run_fork_handlers (atfork_run_prepare, multiple_threads);
|
||||||
|
|
||||||
|
/* If we are not running multiple threads, we do not have to
|
||||||
|
preserve lock state. If fork runs from a signal handler, only
|
||||||
|
@@ -134,7 +134,7 @@ __libc_fork (void)
|
||||||
|
__rtld_lock_initialize (GL(dl_load_lock));
|
||||||
|
|
||||||
|
/* Run the handlers registered for the child. */
|
||||||
|
- __run_fork_handlers (atfork_run_child);
|
||||||
|
+ __run_fork_handlers (atfork_run_child, multiple_threads);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@@ -149,7 +149,7 @@ __libc_fork (void)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run the handlers registered for the parent. */
|
||||||
|
- __run_fork_handlers (atfork_run_parent);
|
||||||
|
+ __run_fork_handlers (atfork_run_parent, multiple_threads);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h
|
||||||
|
index a1c3b26..99ed760 100644
|
||||||
|
--- a/sysdeps/nptl/fork.h
|
||||||
|
+++ b/sysdeps/nptl/fork.h
|
||||||
|
@@ -52,9 +52,11 @@ enum __run_fork_handler_type
|
||||||
|
- atfork_run_child: run all the CHILD_HANDLER and unlocks the internal
|
||||||
|
lock.
|
||||||
|
- atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal
|
||||||
|
- lock. */
|
||||||
|
-extern void __run_fork_handlers (enum __run_fork_handler_type who)
|
||||||
|
- attribute_hidden;
|
||||||
|
+ lock.
|
||||||
|
+
|
||||||
|
+ Perform locking only if DO_LOCKING. */
|
||||||
|
+extern void __run_fork_handlers (enum __run_fork_handler_type who,
|
||||||
|
+ _Bool do_locking) attribute_hidden;
|
||||||
|
|
||||||
|
/* C library side function to register new fork handlers. */
|
||||||
|
extern int __register_atfork (void (*__prepare) (void),
|
60
SOURCES/glibc-rh1746933-1.patch
Normal file
60
SOURCES/glibc-rh1746933-1.patch
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
commit 58d2672f64176fcb323859d3bd5240fb1cf8f25c
|
||||||
|
Author: Wilco Dijkstra <wdijkstr@arm.com>
|
||||||
|
Date: Fri May 10 16:38:21 2019 +0100
|
||||||
|
|
||||||
|
Fix tcache count maximum (BZ #24531)
|
||||||
|
|
||||||
|
The tcache counts[] array is a char, which has a very small range and thus
|
||||||
|
may overflow. When setting tcache_count tunable, there is no overflow check.
|
||||||
|
However the tunable must not be larger than the maximum value of the tcache
|
||||||
|
counts[] array, otherwise it can overflow when filling the tcache.
|
||||||
|
|
||||||
|
[BZ #24531]
|
||||||
|
* malloc/malloc.c (MAX_TCACHE_COUNT): New define.
|
||||||
|
(do_set_tcache_count): Only update if count is small enough.
|
||||||
|
* manual/tunables.texi (glibc.malloc.tcache_count): Document max value.
|
||||||
|
|
||||||
|
(cherry picked from commit 5ad533e8e65092be962e414e0417112c65d154fb)
|
||||||
|
|
||||||
|
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||||
|
index 723d393f529bdb4c..92239b3324584060 100644
|
||||||
|
--- a/malloc/malloc.c
|
||||||
|
+++ b/malloc/malloc.c
|
||||||
|
@@ -2919,6 +2919,8 @@ typedef struct tcache_perthread_struct
|
||||||
|
tcache_entry *entries[TCACHE_MAX_BINS];
|
||||||
|
} tcache_perthread_struct;
|
||||||
|
|
||||||
|
+#define MAX_TCACHE_COUNT 127 /* Maximum value of counts[] entries. */
|
||||||
|
+
|
||||||
|
static __thread bool tcache_shutting_down = false;
|
||||||
|
static __thread tcache_perthread_struct *tcache = NULL;
|
||||||
|
|
||||||
|
@@ -5124,8 +5126,11 @@ static inline int
|
||||||
|
__always_inline
|
||||||
|
do_set_tcache_count (size_t value)
|
||||||
|
{
|
||||||
|
- LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
|
||||||
|
- mp_.tcache_count = value;
|
||||||
|
+ if (value <= MAX_TCACHE_COUNT)
|
||||||
|
+ {
|
||||||
|
+ LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
|
||||||
|
+ mp_.tcache_count = value;
|
||||||
|
+ }
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/manual/tunables.texi b/manual/tunables.texi
|
||||||
|
index bb4819bdf1de273e..9dccf2ee7f8eec17 100644
|
||||||
|
--- a/manual/tunables.texi
|
||||||
|
+++ b/manual/tunables.texi
|
||||||
|
@@ -188,8 +188,8 @@ per-thread cache. The default (and maximum) value is 1032 bytes on
|
||||||
|
|
||||||
|
@deftp Tunable glibc.malloc.tcache_count
|
||||||
|
The maximum number of chunks of each size to cache. The default is 7.
|
||||||
|
-There is no upper limit, other than available system memory. If set
|
||||||
|
-to zero, the per-thread cache is effectively disabled.
|
||||||
|
+The upper limit is 127. If set to zero, the per-thread cache is effectively
|
||||||
|
+disabled.
|
||||||
|
|
||||||
|
The approximate maximum overhead of the per-thread cache is thus equal
|
||||||
|
to the number of bins times the chunk count in each bin times the size
|
37
SOURCES/glibc-rh1746933-2.patch
Normal file
37
SOURCES/glibc-rh1746933-2.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
commit 3640758943c856268bc12a3307838c2a65d2f9ea
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Mon Feb 4 23:46:58 2019 +0000
|
||||||
|
|
||||||
|
Fix assertion in malloc.c:tcache_get.
|
||||||
|
|
||||||
|
One of the warnings that appears with -Wextra is "ordered comparison
|
||||||
|
of pointer with integer zero" in malloc.c:tcache_get, for the
|
||||||
|
assertion:
|
||||||
|
|
||||||
|
assert (tcache->entries[tc_idx] > 0);
|
||||||
|
|
||||||
|
Indeed, a "> 0" comparison does not make sense for
|
||||||
|
tcache->entries[tc_idx], which is a pointer. My guess is that
|
||||||
|
tcache->counts[tc_idx] is what's intended here, and this patch changes
|
||||||
|
the assertion accordingly.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
* malloc/malloc.c (tcache_get): Compare tcache->counts[tc_idx]
|
||||||
|
with 0, not tcache->entries[tc_idx].
|
||||||
|
|
||||||
|
(cherry picked from commit 77dc0d8643aa99c92bf671352b0a8adde705896f)
|
||||||
|
|
||||||
|
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||||
|
index 92239b3324584060..998879aededf0d7c 100644
|
||||||
|
--- a/malloc/malloc.c
|
||||||
|
+++ b/malloc/malloc.c
|
||||||
|
@@ -2948,7 +2948,7 @@ tcache_get (size_t tc_idx)
|
||||||
|
{
|
||||||
|
tcache_entry *e = tcache->entries[tc_idx];
|
||||||
|
assert (tc_idx < TCACHE_MAX_BINS);
|
||||||
|
- assert (tcache->entries[tc_idx] > 0);
|
||||||
|
+ assert (tcache->counts[tc_idx] > 0);
|
||||||
|
tcache->entries[tc_idx] = e->next;
|
||||||
|
--(tcache->counts[tc_idx]);
|
||||||
|
e->key = NULL;
|
92
SOURCES/glibc-rh1746933-3.patch
Normal file
92
SOURCES/glibc-rh1746933-3.patch
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
commit f88c59f4657ac2e0bab8f51f60022ecbe7f12e2e
|
||||||
|
Author: Wilco Dijkstra <wdijkstr@arm.com>
|
||||||
|
Date: Fri May 17 18:16:20 2019 +0100
|
||||||
|
|
||||||
|
Small tcache improvements
|
||||||
|
|
||||||
|
Change the tcache->counts[] entries to uint16_t - this removes
|
||||||
|
the limit set by char and allows a larger tcache. Remove a few
|
||||||
|
redundant asserts.
|
||||||
|
|
||||||
|
bench-malloc-thread with 4 threads is ~15% faster on Cortex-A72.
|
||||||
|
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
|
* malloc/malloc.c (MAX_TCACHE_COUNT): Increase to UINT16_MAX.
|
||||||
|
(tcache_put): Remove redundant assert.
|
||||||
|
(tcache_get): Remove redundant asserts.
|
||||||
|
(__libc_malloc): Check tcache count is not zero.
|
||||||
|
* manual/tunables.texi (glibc.malloc.tcache_count): Update maximum.
|
||||||
|
|
||||||
|
(cherry picked from commit 1f50f2ad854c84ead522bfc7331b46dbe6057d53)
|
||||||
|
|
||||||
|
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||||
|
index 998879aededf0d7c..e6a483d5cf7c4312 100644
|
||||||
|
--- a/malloc/malloc.c
|
||||||
|
+++ b/malloc/malloc.c
|
||||||
|
@@ -321,6 +321,10 @@ __malloc_assert (const char *assertion, const char *file, unsigned int line,
|
||||||
|
/* This is another arbitrary limit, which tunables can change. Each
|
||||||
|
tcache bin will hold at most this number of chunks. */
|
||||||
|
# define TCACHE_FILL_COUNT 7
|
||||||
|
+
|
||||||
|
+/* Maximum chunks in tcache bins for tunables. This value must fit the range
|
||||||
|
+ of tcache->counts[] entries, else they may overflow. */
|
||||||
|
+# define MAX_TCACHE_COUNT UINT16_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2915,12 +2919,10 @@ typedef struct tcache_entry
|
||||||
|
time), this is for performance reasons. */
|
||||||
|
typedef struct tcache_perthread_struct
|
||||||
|
{
|
||||||
|
- char counts[TCACHE_MAX_BINS];
|
||||||
|
+ uint16_t counts[TCACHE_MAX_BINS];
|
||||||
|
tcache_entry *entries[TCACHE_MAX_BINS];
|
||||||
|
} tcache_perthread_struct;
|
||||||
|
|
||||||
|
-#define MAX_TCACHE_COUNT 127 /* Maximum value of counts[] entries. */
|
||||||
|
-
|
||||||
|
static __thread bool tcache_shutting_down = false;
|
||||||
|
static __thread tcache_perthread_struct *tcache = NULL;
|
||||||
|
|
||||||
|
@@ -2930,7 +2932,6 @@ static __always_inline void
|
||||||
|
tcache_put (mchunkptr chunk, size_t tc_idx)
|
||||||
|
{
|
||||||
|
tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
|
||||||
|
- assert (tc_idx < TCACHE_MAX_BINS);
|
||||||
|
|
||||||
|
/* Mark this chunk as "in the tcache" so the test in _int_free will
|
||||||
|
detect a double free. */
|
||||||
|
@@ -2947,8 +2948,6 @@ static __always_inline void *
|
||||||
|
tcache_get (size_t tc_idx)
|
||||||
|
{
|
||||||
|
tcache_entry *e = tcache->entries[tc_idx];
|
||||||
|
- assert (tc_idx < TCACHE_MAX_BINS);
|
||||||
|
- assert (tcache->counts[tc_idx] > 0);
|
||||||
|
tcache->entries[tc_idx] = e->next;
|
||||||
|
--(tcache->counts[tc_idx]);
|
||||||
|
e->key = NULL;
|
||||||
|
@@ -3053,9 +3052,8 @@ __libc_malloc (size_t bytes)
|
||||||
|
|
||||||
|
DIAG_PUSH_NEEDS_COMMENT;
|
||||||
|
if (tc_idx < mp_.tcache_bins
|
||||||
|
- /*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */
|
||||||
|
&& tcache
|
||||||
|
- && tcache->entries[tc_idx] != NULL)
|
||||||
|
+ && tcache->counts[tc_idx] > 0)
|
||||||
|
{
|
||||||
|
return tcache_get (tc_idx);
|
||||||
|
}
|
||||||
|
diff --git a/manual/tunables.texi b/manual/tunables.texi
|
||||||
|
index 9dccf2ee7f8eec17..f6c49250e3889ddd 100644
|
||||||
|
--- a/manual/tunables.texi
|
||||||
|
+++ b/manual/tunables.texi
|
||||||
|
@@ -188,7 +188,7 @@ per-thread cache. The default (and maximum) value is 1032 bytes on
|
||||||
|
|
||||||
|
@deftp Tunable glibc.malloc.tcache_count
|
||||||
|
The maximum number of chunks of each size to cache. The default is 7.
|
||||||
|
-The upper limit is 127. If set to zero, the per-thread cache is effectively
|
||||||
|
+The upper limit is 65535. If set to zero, the per-thread cache is effectively
|
||||||
|
disabled.
|
||||||
|
|
||||||
|
The approximate maximum overhead of the per-thread cache is thus equal
|
156
SOURCES/glibc-rh1747453.patch
Normal file
156
SOURCES/glibc-rh1747453.patch
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
commit 8692ebdb1259be60c545fa509d4852b26703777e
|
||||||
|
Author: David Newall <glibc@davidnewall.com>
|
||||||
|
Date: Mon Feb 4 13:35:11 2019 +0100
|
||||||
|
|
||||||
|
elf: Implement --preload option for the dynamic linker
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 9cf5cd8dfd..db6a2a0c29 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -354,7 +354,8 @@ endif
|
||||||
|
|
||||||
|
ifeq (yes,$(build-shared))
|
||||||
|
ifeq ($(run-built-tests),yes)
|
||||||
|
-tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out
|
||||||
|
+tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \
|
||||||
|
+ $(objpfx)tst-rtld-preload.out
|
||||||
|
endif
|
||||||
|
tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
|
||||||
|
$(objpfx)check-localplt.out $(objpfx)check-initfini.out
|
||||||
|
@@ -883,6 +884,15 @@ $(objpfx)tst-rtld-load-self.out: tst-rtld-load-self.sh $(objpfx)ld.so
|
||||||
|
$(SHELL) $^ '$(test-wrapper)' '$(test-wrapper-env)' > $@; \
|
||||||
|
$(evaluate-test)
|
||||||
|
|
||||||
|
+tst-rtld-preload-OBJS = $(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so)))
|
||||||
|
+$(objpfx)tst-rtld-preload.out: tst-rtld-preload.sh $(objpfx)ld.so \
|
||||||
|
+ $(objpfx)preloadtest \
|
||||||
|
+ $(preloadtest-preloads:%=$(objpfx)%.so)
|
||||||
|
+ $(SHELL) $< $(objpfx)ld.so $(objpfx)preloadtest \
|
||||||
|
+ '$(test-wrapper)' '$(test-wrapper-env)' '$(run_program_env)' \
|
||||||
|
+ '$(rpath-link)' '$(tst-rtld-preload-OBJS)' > $@; \
|
||||||
|
+ $(evaluate-test)
|
||||||
|
+
|
||||||
|
$(objpfx)initfirst: $(libdl)
|
||||||
|
$(objpfx)initfirst.out: $(objpfx)firstobj.so
|
||||||
|
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index 5d97f41b7b..5a90e78ed6 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -826,15 +826,18 @@ static const char *library_path attribute_relro;
|
||||||
|
static const char *preloadlist attribute_relro;
|
||||||
|
/* Nonzero if information about versions has to be printed. */
|
||||||
|
static int version_info attribute_relro;
|
||||||
|
+/* The preload list passed as a command argument. */
|
||||||
|
+static const char *preloadarg attribute_relro;
|
||||||
|
|
||||||
|
/* The LD_PRELOAD environment variable gives list of libraries
|
||||||
|
separated by white space or colons that are loaded before the
|
||||||
|
executable's dependencies and prepended to the global scope list.
|
||||||
|
(If the binary is running setuid all elements containing a '/' are
|
||||||
|
ignored since it is insecure.) Return the number of preloads
|
||||||
|
- performed. */
|
||||||
|
+ performed. Ditto for --preload command argument. */
|
||||||
|
unsigned int
|
||||||
|
-handle_ld_preload (const char *preloadlist, struct link_map *main_map)
|
||||||
|
+handle_preload_list (const char *preloadlist, struct link_map *main_map,
|
||||||
|
+ const char *where)
|
||||||
|
{
|
||||||
|
unsigned int npreloads = 0;
|
||||||
|
const char *p = preloadlist;
|
||||||
|
@@ -858,7 +861,7 @@ handle_ld_preload (const char *preloadlist, struct link_map *main_map)
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (dso_name_valid_for_suid (fname))
|
||||||
|
- npreloads += do_preload (fname, main_map, "LD_PRELOAD");
|
||||||
|
+ npreloads += do_preload (fname, main_map, where);
|
||||||
|
}
|
||||||
|
return npreloads;
|
||||||
|
}
|
||||||
|
@@ -974,6 +977,13 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
|
{
|
||||||
|
process_dl_audit (_dl_argv[2]);
|
||||||
|
|
||||||
|
+ _dl_skip_args += 2;
|
||||||
|
+ _dl_argc -= 2;
|
||||||
|
+ _dl_argv += 2;
|
||||||
|
+ }
|
||||||
|
+ else if (! strcmp (_dl_argv[1], "--preload") && _dl_argc > 2)
|
||||||
|
+ {
|
||||||
|
+ preloadarg = _dl_argv[2];
|
||||||
|
_dl_skip_args += 2;
|
||||||
|
_dl_argc -= 2;
|
||||||
|
_dl_argv += 2;
|
||||||
|
@@ -1006,7 +1016,8 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||||
|
variable LD_LIBRARY_PATH\n\
|
||||||
|
--inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\
|
||||||
|
in LIST\n\
|
||||||
|
- --audit LIST use objects named in LIST as auditors\n");
|
||||||
|
+ --audit LIST use objects named in LIST as auditors\n\
|
||||||
|
+ --preload LIST preload objects named in LIST\n");
|
||||||
|
|
||||||
|
++_dl_skip_args;
|
||||||
|
--_dl_argc;
|
||||||
|
@@ -1620,7 +1631,16 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||||
|
if (__glibc_unlikely (preloadlist != NULL))
|
||||||
|
{
|
||||||
|
HP_TIMING_NOW (start);
|
||||||
|
- npreloads += handle_ld_preload (preloadlist, main_map);
|
||||||
|
+ npreloads += handle_preload_list (preloadlist, main_map, "LD_PRELOAD");
|
||||||
|
+ HP_TIMING_NOW (stop);
|
||||||
|
+ HP_TIMING_DIFF (diff, start, stop);
|
||||||
|
+ HP_TIMING_ACCUM_NT (load_time, diff);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (__glibc_unlikely (preloadarg != NULL))
|
||||||
|
+ {
|
||||||
|
+ HP_TIMING_NOW (start);
|
||||||
|
+ npreloads += handle_preload_list (preloadarg, main_map, "--preload");
|
||||||
|
HP_TIMING_NOW (stop);
|
||||||
|
HP_TIMING_DIFF (diff, start, stop);
|
||||||
|
HP_TIMING_ACCUM_NT (load_time, diff);
|
||||||
|
diff --git a/elf/tst-rtld-preload.sh b/elf/tst-rtld-preload.sh
|
||||||
|
new file mode 100755
|
||||||
|
index 0000000000..f0c0ca11ba
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-rtld-preload.sh
|
||||||
|
@@ -0,0 +1,38 @@
|
||||||
|
+#!/bin/sh
|
||||||
|
+# Test --preload argument ld.so.
|
||||||
|
+# Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+# This file is part of the GNU C Library.
|
||||||
|
+#
|
||||||
|
+# The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+# modify it under the terms of the GNU Lesser General Public
|
||||||
|
+# License as published by the Free Software Foundation; either
|
||||||
|
+# version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+#
|
||||||
|
+# The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+# Lesser General Public License for more details.
|
||||||
|
+#
|
||||||
|
+# You should have received a copy of the GNU Lesser General Public
|
||||||
|
+# License along with the GNU C Library; if not, see
|
||||||
|
+# <http://www.gnu.org/licenses/>.
|
||||||
|
+
|
||||||
|
+set -e
|
||||||
|
+
|
||||||
|
+rtld=$1
|
||||||
|
+test_program=$2
|
||||||
|
+test_wrapper=$3
|
||||||
|
+test_wrapper_env=$4
|
||||||
|
+run_program_env=$5
|
||||||
|
+library_path=$6
|
||||||
|
+preload=$7
|
||||||
|
+
|
||||||
|
+echo "# [${test_wrapper}] [$rtld] [--library-path] [$library_path]" \
|
||||||
|
+ "[--preload] [$preload] [$test_program]"
|
||||||
|
+${test_wrapper_env} \
|
||||||
|
+${run_program_env} \
|
||||||
|
+${test_wrapper} $rtld --library-path "$library_path" \
|
||||||
|
+ --preload "$preload" $test_program 2>&1 && rc=0 || rc=$?
|
||||||
|
+echo "# exit status $rc"
|
||||||
|
+
|
||||||
|
+exit $rc
|
168
SOURCES/glibc-rh1747502-1.patch
Normal file
168
SOURCES/glibc-rh1747502-1.patch
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
commit 561b0bec4448f0302cb4915bf67c919bde4a1c57
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Fri Jul 6 01:10:41 2018 -0400
|
||||||
|
|
||||||
|
Add test-in-container infrastructure.
|
||||||
|
|
||||||
|
* Makefile (testroot.pristine): New rules to initialize the
|
||||||
|
test-in-container "testroot".
|
||||||
|
* Makerules (all-testsuite): Add tests-container.
|
||||||
|
* Rules (tests-expected): Add tests-container.
|
||||||
|
(binaries-all-tests): Likewise.
|
||||||
|
(tests-container): New, run these tests in the testroot container.
|
||||||
|
* support/links-dso-program-c.c: New.
|
||||||
|
* support/links-dso-program.cc: New.
|
||||||
|
* support/test-container.c: New.
|
||||||
|
* support/shell-container.c: New.
|
||||||
|
* support/echo-container.c: New.
|
||||||
|
* support/true-container.c: New.
|
||||||
|
* support/xmkdirp.c: New.
|
||||||
|
* support/xsymlink.c: New.
|
||||||
|
* support/support_paths.c: New.
|
||||||
|
* support/support.h: Add support paths prototypes.
|
||||||
|
* support/xunistd.h: Add xmkdirp () and xsymlink ().
|
||||||
|
|
||||||
|
* nss/tst-nss-test3.c: Convert to test-in-container.
|
||||||
|
* nss/tst-nss-test3.root/: New.
|
||||||
|
|
||||||
|
(note: support/ already present, not needed; sample test not included)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index d3f25a5..3df55e6 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -340,6 +340,62 @@ define summarize-tests
|
||||||
|
@! egrep -q -v '^(X?PASS|XFAIL|UNSUPPORTED):' $(objpfx)$1
|
||||||
|
endef
|
||||||
|
|
||||||
|
+# The intention here is to do ONE install of our build into the
|
||||||
|
+# testroot.pristine/ directory, then rsync (internal to
|
||||||
|
+# support/test-container) that to testroot.root/ at the start of each
|
||||||
|
+# test. That way we can promise each test a "clean" install, without
|
||||||
|
+# having to do the install for each test.
|
||||||
|
+#
|
||||||
|
+# In addition, we have to copy some files (which we build) into this
|
||||||
|
+# root in addition to what glibc installs. For example, many tests
|
||||||
|
+# require additional programs including /bin/sh, /bin/true, and
|
||||||
|
+# /bin/echo, all of which we build below to limit library dependencies
|
||||||
|
+# to just those things in glibc and language support libraries which
|
||||||
|
+# we also copy into the into the rootfs. To determine what language
|
||||||
|
+# support libraries we need we build a "test" program in either C or
|
||||||
|
+# (if available) C++ just so we can copy in any shared objects
|
||||||
|
+# (which we do not build) that GCC-compiled programs depend on.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ifeq (,$(CXX))
|
||||||
|
+LINKS_DSO_PROGRAM = links-dso-program-c
|
||||||
|
+else
|
||||||
|
+LINKS_DSO_PROGRAM = links-dso-program
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
+$(tests-container) $(addsuffix /tests,$(subdirs)) : \
|
||||||
|
+ $(objpfx)testroot.pristine/install.stamp
|
||||||
|
+$(objpfx)testroot.pristine/install.stamp :
|
||||||
|
+ test -d $(objpfx)testroot.pristine || \
|
||||||
|
+ mkdir $(objpfx)testroot.pristine
|
||||||
|
+ # We need a working /bin/sh for some of the tests.
|
||||||
|
+ test -d $(objpfx)testroot.pristine/bin || \
|
||||||
|
+ mkdir $(objpfx)testroot.pristine/bin
|
||||||
|
+ cp $(objpfx)support/shell-container $(objpfx)testroot.pristine/bin/sh
|
||||||
|
+ cp $(objpfx)support/echo-container $(objpfx)testroot.pristine/bin/echo
|
||||||
|
+ cp $(objpfx)support/true-container $(objpfx)testroot.pristine/bin/true
|
||||||
|
+ # Copy these DSOs first so we can overwrite them with our own.
|
||||||
|
+ for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \
|
||||||
|
+ $(objpfx)elf/$(rtld-installed-name) \
|
||||||
|
+ $(objpfx)testroot.pristine/bin/sh \
|
||||||
|
+ | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\
|
||||||
|
+ do \
|
||||||
|
+ test -d `dirname $(objpfx)testroot.pristine$$dso` || \
|
||||||
|
+ mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\
|
||||||
|
+ $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\
|
||||||
|
+ done
|
||||||
|
+ for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \
|
||||||
|
+ $(objpfx)elf/$(rtld-installed-name) \
|
||||||
|
+ $(objpfx)support/$(LINKS_DSO_PROGRAM) \
|
||||||
|
+ | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\
|
||||||
|
+ do \
|
||||||
|
+ test -d `dirname $(objpfx)testroot.pristine$$dso` || \
|
||||||
|
+ mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\
|
||||||
|
+ $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\
|
||||||
|
+ done
|
||||||
|
+ $(MAKE) install DESTDIR=$(objpfx)testroot.pristine
|
||||||
|
+ touch $(objpfx)testroot.pristine/install.stamp
|
||||||
|
+
|
||||||
|
tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special))
|
||||||
|
tests: $(tests-special)
|
||||||
|
$(..)scripts/merge-test-results.sh -s $(objpfx) "" \
|
||||||
|
diff --git a/Makerules b/Makerules
|
||||||
|
index a10a0b4..5d6434c 100644
|
||||||
|
--- a/Makerules
|
||||||
|
+++ b/Makerules
|
||||||
|
@@ -1369,7 +1369,8 @@ xcheck: xtests
|
||||||
|
# The only difference between MODULE_NAME=testsuite and MODULE_NAME=nonlib is
|
||||||
|
# that almost all internal declarations from config.h, libc-symbols.h, and
|
||||||
|
# include/*.h are not available to 'testsuite' code, but are to 'nonlib' code.
|
||||||
|
-all-testsuite := $(strip $(tests) $(xtests) $(test-srcs) $(test-extras))
|
||||||
|
+all-testsuite := $(strip $(tests) $(xtests) $(test-srcs) $(test-extras) \
|
||||||
|
+ $(tests-container))
|
||||||
|
ifneq (,$(all-testsuite))
|
||||||
|
cpp-srcs-left = $(all-testsuite)
|
||||||
|
lib := testsuite
|
||||||
|
diff --git a/Rules b/Rules
|
||||||
|
index 706c8a7..5abb727 100644
|
||||||
|
--- a/Rules
|
||||||
|
+++ b/Rules
|
||||||
|
@@ -130,12 +130,14 @@ others: $(py-const)
|
||||||
|
|
||||||
|
ifeq ($(run-built-tests),no)
|
||||||
|
tests: $(addprefix $(objpfx),$(filter-out $(tests-unsupported), \
|
||||||
|
- $(tests) $(tests-internal)) \
|
||||||
|
+ $(tests) $(tests-internal) \
|
||||||
|
+ $(tests-container)) \
|
||||||
|
$(test-srcs)) $(tests-special) \
|
||||||
|
$(tests-printers-programs)
|
||||||
|
xtests: tests $(xtests-special)
|
||||||
|
else
|
||||||
|
tests: $(tests:%=$(objpfx)%.out) $(tests-internal:%=$(objpfx)%.out) \
|
||||||
|
+ $(tests-container:%=$(objpfx)%.out) \
|
||||||
|
$(tests-special) $(tests-printers-out)
|
||||||
|
xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special)
|
||||||
|
endif
|
||||||
|
@@ -145,7 +147,8 @@ xtests-special-notdir = $(patsubst $(objpfx)%, %, $(xtests-special))
|
||||||
|
ifeq ($(run-built-tests),no)
|
||||||
|
tests-expected =
|
||||||
|
else
|
||||||
|
-tests-expected = $(tests) $(tests-internal) $(tests-printers)
|
||||||
|
+tests-expected = $(tests) $(tests-internal) $(tests-printers) \
|
||||||
|
+ $(tests-container)
|
||||||
|
endif
|
||||||
|
tests:
|
||||||
|
$(..)scripts/merge-test-results.sh -s $(objpfx) $(subdir) \
|
||||||
|
@@ -158,7 +161,8 @@ xtests:
|
||||||
|
|
||||||
|
ifeq ($(build-programs),yes)
|
||||||
|
binaries-all-notests = $(others) $(sysdep-others)
|
||||||
|
-binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs)
|
||||||
|
+binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs) \
|
||||||
|
+ $(tests-container)
|
||||||
|
binaries-all = $(binaries-all-notests) $(binaries-all-tests)
|
||||||
|
binaries-static-notests = $(others-static)
|
||||||
|
binaries-static-tests = $(tests-static) $(xtests-static)
|
||||||
|
@@ -248,6 +252,17 @@ $(objpfx)%.out: /dev/null $(objpfx)% # Make it 2nd arg for canned sequence.
|
||||||
|
$(make-test-out) > $@; \
|
||||||
|
$(evaluate-test)
|
||||||
|
|
||||||
|
+
|
||||||
|
+# Any tests that require an isolated container (filesystem, network
|
||||||
|
+# and pid namespaces) in which to run, should be added to
|
||||||
|
+# tests-container.
|
||||||
|
+$(tests-container:%=$(objpfx)%.out): $(objpfx)%.out : $(if $(wildcard $(objpfx)%.files),$(objpfx)%.files,/dev/null) $(objpfx)%
|
||||||
|
+ $(test-wrapper-env) $(run-program-env) $(run-via-rtld-prefix) \
|
||||||
|
+ $(common-objpfx)support/test-container env $(run-program-env) $($*-ENV) \
|
||||||
|
+ $(host-test-program-cmd) $($*-ARGS) > $@; \
|
||||||
|
+ $(evaluate-test)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
# tests-unsupported lists tests that we will not try to build at all in
|
||||||
|
# this configuration. Note this runs every time because it does not
|
||||||
|
# actually create its target. The dependency on Makefile is meant to
|
48
SOURCES/glibc-rh1747502-2.patch
Normal file
48
SOURCES/glibc-rh1747502-2.patch
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
commit bd598da9f454bc1091b4ebe0303b07e6f96ca130
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Tue Dec 4 16:52:39 2018 +0000
|
||||||
|
|
||||||
|
Stop test-in-container trying to run other-OS binaries.
|
||||||
|
|
||||||
|
I noticed that, now that build-many-glibcs.py no longer copies glibc
|
||||||
|
sources, I was getting core dumps in my glibc source directories. The
|
||||||
|
cause appears to be, from the i686-gnu build:
|
||||||
|
|
||||||
|
for dso in ` env LD_TRACE_LOADED_OBJECTS=1 \
|
||||||
|
/scratch/jmyers/glibc-bot/build/glibcs/i686-gnu/glibc/elf/ld.so.1 \
|
||||||
|
/scratch/jmyers/glibc-bot/build/glibcs/i686-gnu/glibc/testroot.pristine/bin/sh \
|
||||||
|
[...]
|
||||||
|
Segmentation fault (core dumped)
|
||||||
|
|
||||||
|
In this case, the x86 architecture means the binary executes, but
|
||||||
|
dumps core rather than actually working.
|
||||||
|
|
||||||
|
Anything involving running the newly built glibc should only be done
|
||||||
|
ifeq ($(run-built-tests),yes). This patch conditions the relevant
|
||||||
|
part of the testroot setup accordingly.
|
||||||
|
|
||||||
|
Tested for x86_64, and with build-many-glibcs.py for i686-gnu.
|
||||||
|
|
||||||
|
* Makefile ($(objpfx)testroot.pristine/install.stamp): Do not run
|
||||||
|
dynamic linker unless [$(run-built-tests) = yes].
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index b4703e4..fd73d9b 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -374,6 +374,7 @@ $(objpfx)testroot.pristine/install.stamp :
|
||||||
|
cp $(objpfx)support/shell-container $(objpfx)testroot.pristine/bin/sh
|
||||||
|
cp $(objpfx)support/echo-container $(objpfx)testroot.pristine/bin/echo
|
||||||
|
cp $(objpfx)support/true-container $(objpfx)testroot.pristine/bin/true
|
||||||
|
+ifeq ($(run-built-tests),yes)
|
||||||
|
# Copy these DSOs first so we can overwrite them with our own.
|
||||||
|
for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \
|
||||||
|
$(objpfx)elf/$(rtld-installed-name) \
|
||||||
|
@@ -393,6 +394,7 @@ $(objpfx)testroot.pristine/install.stamp :
|
||||||
|
mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\
|
||||||
|
$(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\
|
||||||
|
done
|
||||||
|
+endif
|
||||||
|
$(MAKE) install DESTDIR=$(objpfx)testroot.pristine
|
||||||
|
touch $(objpfx)testroot.pristine/install.stamp
|
||||||
|
|
40
SOURCES/glibc-rh1747502-3.patch
Normal file
40
SOURCES/glibc-rh1747502-3.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
commit 95da14dac04b494149290d85bc5306226e30839e
|
||||||
|
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||||
|
Date: Mon Jul 22 16:30:45 2019 -0300
|
||||||
|
|
||||||
|
test-container: Avoid copying unintended system libraries
|
||||||
|
|
||||||
|
Some DSOs are distributed in hardware capability directories, e.g.
|
||||||
|
/usr/lib64/power7/libc.so.6
|
||||||
|
Whenever the processor is able to use one of these hardware-enabled
|
||||||
|
DSOs, testroot.pristine ends up with copies of glibc-provided libraries
|
||||||
|
from the system because it can't overwrite or remove them.
|
||||||
|
|
||||||
|
This patch avoids the unintended copies by executing ld.so with the same
|
||||||
|
arguments passed to each glibc test.
|
||||||
|
|
||||||
|
* Makefile (testroot.pristine/install.stamp): Execute ld.so with
|
||||||
|
the same arguments used in all tests.
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index dc5de7a..a4ed747 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -383,7 +383,7 @@ $(objpfx)testroot.pristine/install.stamp :
|
||||||
|
ifeq ($(run-built-tests),yes)
|
||||||
|
# Copy these DSOs first so we can overwrite them with our own.
|
||||||
|
for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \
|
||||||
|
- $(objpfx)elf/$(rtld-installed-name) \
|
||||||
|
+ $(rtld-prefix) \
|
||||||
|
$(objpfx)testroot.pristine/bin/sh \
|
||||||
|
| grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\
|
||||||
|
do \
|
||||||
|
@@ -392,7 +392,7 @@ ifeq ($(run-built-tests),yes)
|
||||||
|
$(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\
|
||||||
|
done
|
||||||
|
for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \
|
||||||
|
- $(objpfx)elf/$(rtld-installed-name) \
|
||||||
|
+ $(rtld-prefix) \
|
||||||
|
$(objpfx)support/$(LINKS_DSO_PROGRAM) \
|
||||||
|
| grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\
|
||||||
|
do \
|
31
SOURCES/glibc-rh1747502-4.patch
Normal file
31
SOURCES/glibc-rh1747502-4.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
commit 35e038c1d2ccb3a75395662f9c4f28d85a61444f
|
||||||
|
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||||
|
Date: Mon Jul 22 17:34:13 2019 -0300
|
||||||
|
|
||||||
|
test-container: Install with $(all-subdirs) [BZ #24794]
|
||||||
|
|
||||||
|
Whenever a sub-make is created, it inherits the variable subdirs from its
|
||||||
|
parent. This is also true when make check is called with a restricted
|
||||||
|
list of subdirs. In this scenario, make install is executed "partially"
|
||||||
|
and testroot.pristine ends up with an incomplete installation.
|
||||||
|
|
||||||
|
[BZ #24794]
|
||||||
|
* Makefile (testroot.pristine/install.stamp): Pass
|
||||||
|
subdirs='$(all-subdirs)' to make install.
|
||||||
|
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index a4ed747..9fbf705 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -401,7 +401,8 @@ ifeq ($(run-built-tests),yes)
|
||||||
|
$(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\
|
||||||
|
done
|
||||||
|
endif
|
||||||
|
- $(MAKE) install DESTDIR=$(objpfx)testroot.pristine
|
||||||
|
+ $(MAKE) install DESTDIR=$(objpfx)testroot.pristine \
|
||||||
|
+ subdirs='$(all-subdirs)'
|
||||||
|
touch $(objpfx)testroot.pristine/install.stamp
|
||||||
|
|
||||||
|
tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special))
|
56
SOURCES/glibc-rh1747502-5.patch
Normal file
56
SOURCES/glibc-rh1747502-5.patch
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
commit 7db1fe38de21831d53ceab9ae83493d8d1aec601
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Tue Oct 22 20:24:10 2019 +0000
|
||||||
|
|
||||||
|
Fix testroot.pristine creation copying dynamic linker.
|
||||||
|
|
||||||
|
This patch addresses an issue reported in
|
||||||
|
<https://sourceware.org/ml/libc-alpha/2019-07/msg00661.html> where the
|
||||||
|
creation of testroot.pristine, on encountering
|
||||||
|
LD_TRACE_LOADED_OBJECTS=1 of the form
|
||||||
|
|
||||||
|
libc.so.6 => /scratch/jmyers/glibc/mbs/obj/glibc-8-0-mips64-linux-gnu-x86_64-linux-gnu/default/libc.so.6 (0x772dd000)
|
||||||
|
/lib32/ld.so.1 => /scratch/jmyers/glibc/mbs/obj/glibc-8-0-mips64-linux-gnu-x86_64-linux-gnu/default/elf/ld.so.1 (0x7747b000)
|
||||||
|
|
||||||
|
tries to copy /lib32/ld.so.1 (which does not exist) into the testroot
|
||||||
|
instead of copying the path on the RHS of "=>", which does exist,
|
||||||
|
because the Makefile logic assumes that the path on such a line with
|
||||||
|
'/' should be copied, when if there are such paths on both the LHS and
|
||||||
|
the RHS of "=>", only the one on the RHS necessarily exists and so
|
||||||
|
only that should be copied. The patch follows the approach suggested
|
||||||
|
by DJ in <https://sourceware.org/ml/libc-alpha/2019-07/msg00662.html>,
|
||||||
|
with the suggestion from Andreas in
|
||||||
|
<https://sourceware.org/ml/libc-alpha/2019-10/msg00514.html> of a
|
||||||
|
single sed command in place of pipeline of grep and three sed
|
||||||
|
commands.
|
||||||
|
|
||||||
|
Tested for x86_64, with and without --enable-hardcoded-path-in-tests;
|
||||||
|
a previous version with multiple sed commands, implementing the same
|
||||||
|
logic, also tested for MIPS, with and without
|
||||||
|
--enable-hardcoded-path-in-tests, to confirm it fixes the original
|
||||||
|
problem.
|
||||||
|
|
||||||
|
Co-authored-by: DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index d7e4be9..0711b97 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -564,7 +564,7 @@ ifeq ($(run-built-tests),yes)
|
||||||
|
for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \
|
||||||
|
$(rtld-prefix) \
|
||||||
|
$(objpfx)testroot.pristine/bin/sh \
|
||||||
|
- | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\
|
||||||
|
+ | sed -n '/\//{s@.*=> /@/@;s/^[^/]*//;s/ .*//p;}'` ;\
|
||||||
|
do \
|
||||||
|
test -d `dirname $(objpfx)testroot.pristine$$dso` || \
|
||||||
|
mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\
|
||||||
|
@@ -573,7 +573,7 @@ ifeq ($(run-built-tests),yes)
|
||||||
|
for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \
|
||||||
|
$(rtld-prefix) \
|
||||||
|
$(objpfx)support/$(LINKS_DSO_PROGRAM) \
|
||||||
|
- | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\
|
||||||
|
+ | sed -n '/\//{s@.*=> /@/@;s/^[^/]*//;s/ .*//p;}'` ;\
|
||||||
|
do \
|
||||||
|
test -d `dirname $(objpfx)testroot.pristine$$dso` || \
|
||||||
|
mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\
|
56
SOURCES/glibc-rh1747502-6.patch
Normal file
56
SOURCES/glibc-rh1747502-6.patch
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
commit c7ac9caaae6f8d02d4e0c7618d4991324a084c66
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Mon May 13 13:57:37 2019 -0300
|
||||||
|
|
||||||
|
support: Export bindir path on support_path
|
||||||
|
|
||||||
|
Checked on x86_64-linux-gnu.
|
||||||
|
|
||||||
|
* support/Makefile (CFLAGS-support_paths.c): Add -DBINDIR_PATH.
|
||||||
|
* support/support.h (support_bindir_prefix): New variable.
|
||||||
|
* support/support_paths.c [BINDIR_PATH] (support_bindir_prefix):
|
||||||
|
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index 64044f6..fe416cd 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -179,7 +179,8 @@ CFLAGS-support_paths.c = \
|
||||||
|
-DOBJDIR_PATH=\"`cd $(objpfx)/..; pwd`\" \
|
||||||
|
-DOBJDIR_ELF_LDSO_PATH=\"`cd $(objpfx)/..; pwd`/elf/$(rtld-installed-name)\" \
|
||||||
|
-DINSTDIR_PATH=\"$(prefix)\" \
|
||||||
|
- -DLIBDIR_PATH=\"$(libdir)\"
|
||||||
|
+ -DLIBDIR_PATH=\"$(libdir)\" \
|
||||||
|
+ -DBINDIR_PATH=\"$(bindir)\"
|
||||||
|
|
||||||
|
ifeq (,$(CXX))
|
||||||
|
LINKS_DSO_PROGRAM = links-dso-program-c
|
||||||
|
diff --git a/support/support.h b/support/support.h
|
||||||
|
index 97fef2c..b162491 100644
|
||||||
|
--- a/support/support.h
|
||||||
|
+++ b/support/support.h
|
||||||
|
@@ -105,6 +105,8 @@ extern const char support_objdir_elf_ldso[];
|
||||||
|
extern const char support_install_prefix[];
|
||||||
|
/* Corresponds to the install's lib/ or lib64/ directory. */
|
||||||
|
extern const char support_libdir_prefix[];
|
||||||
|
+/* Corresponds to the install's bin/ directory. */
|
||||||
|
+extern const char support_bindir_prefix[];
|
||||||
|
|
||||||
|
extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *,
|
||||||
|
size_t, unsigned int);
|
||||||
|
diff --git a/support/support_paths.c b/support/support_paths.c
|
||||||
|
index 937e6e1..75634aa 100644
|
||||||
|
--- a/support/support_paths.c
|
||||||
|
+++ b/support/support_paths.c
|
||||||
|
@@ -57,3 +57,10 @@ const char support_libdir_prefix[] = LIBDIR_PATH;
|
||||||
|
#else
|
||||||
|
# error please -DLIBDIR_PATH=something in the Makefile
|
||||||
|
#endif
|
||||||
|
+
|
||||||
|
+#ifdef BINDIR_PATH
|
||||||
|
+/* Corresponds to the install's bin/ directory. */
|
||||||
|
+const char support_bindir_prefix[] = BINDIR_PATH;
|
||||||
|
+#else
|
||||||
|
+# error please -DBINDIR_PATH=something in the Makefile
|
||||||
|
+#endif
|
46
SOURCES/glibc-rh1747502-7.patch
Normal file
46
SOURCES/glibc-rh1747502-7.patch
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
From 354e4c1adddb1da19c1043e3e5db61ee2148d912 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||||
|
Date: Wed, 24 Jul 2019 19:49:00 -0300
|
||||||
|
Subject: test-container: Install with $(sorted-subdirs) [BZ #24794]
|
||||||
|
|
||||||
|
Commit 35e038c1d2ccb3a75395662f9c4f28d85a61444f started to use an
|
||||||
|
incomplete list of subdirs based on $(all-subdirs) causing
|
||||||
|
testroot.pristine to miss files from nss.
|
||||||
|
|
||||||
|
Tested if the list of files in testroot.pristine remains the same.
|
||||||
|
|
||||||
|
[BZ #24794]
|
||||||
|
* Makeconfig (all-subdirs): Improved source comments.
|
||||||
|
* Makefile (testroot.pristine/install.stamp): Pass
|
||||||
|
subdirs='$(sorted-subdirs)' to make install.
|
||||||
|
|
||||||
|
diff --git a/Makeconfig b/Makeconfig
|
||||||
|
index 0e386fbc19..fd36c58c04 100644
|
||||||
|
--- a/Makeconfig
|
||||||
|
+++ b/Makeconfig
|
||||||
|
@@ -1267,9 +1267,9 @@ else
|
||||||
|
libsupport = $(common-objpfx)support/libsupport.a
|
||||||
|
endif
|
||||||
|
|
||||||
|
-# These are the subdirectories containing the library source. The order
|
||||||
|
-# is more or less arbitrary. The sorting step will take care of the
|
||||||
|
-# dependencies.
|
||||||
|
+# This is a partial list of subdirectories containing the library source.
|
||||||
|
+# The order is more or less arbitrary. The sorting step will take care of the
|
||||||
|
+# dependencies and generate sorted-subdirs dynamically.
|
||||||
|
all-subdirs = csu assert ctype locale intl catgets math setjmp signal \
|
||||||
|
stdlib stdio-common libio malloc string wcsmbs time dirent \
|
||||||
|
grp pwd posix io termios resource misc socket sysvipc gmon \
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 9fbf705200..ac1125853b 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -402,7 +402,7 @@ ifeq ($(run-built-tests),yes)
|
||||||
|
done
|
||||||
|
endif
|
||||||
|
$(MAKE) install DESTDIR=$(objpfx)testroot.pristine \
|
||||||
|
- subdirs='$(all-subdirs)'
|
||||||
|
+ subdirs='$(sorted-subdirs)'
|
||||||
|
touch $(objpfx)testroot.pristine/install.stamp
|
||||||
|
|
||||||
|
tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special))
|
50
SOURCES/glibc-rh1747502-8.patch
Normal file
50
SOURCES/glibc-rh1747502-8.patch
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
commit d50f09181eca10a91fd9035bb90711b265770dc9
|
||||||
|
Author: Alexandra Hájková <ahajkova@redhat.com>
|
||||||
|
Date: Mon May 13 19:31:53 2019 +0200
|
||||||
|
|
||||||
|
support: Add support_install_rootsbindir
|
||||||
|
|
||||||
|
Reviewed by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index fe416cd..18d39f5 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -180,7 +180,8 @@ CFLAGS-support_paths.c = \
|
||||||
|
-DOBJDIR_ELF_LDSO_PATH=\"`cd $(objpfx)/..; pwd`/elf/$(rtld-installed-name)\" \
|
||||||
|
-DINSTDIR_PATH=\"$(prefix)\" \
|
||||||
|
-DLIBDIR_PATH=\"$(libdir)\" \
|
||||||
|
- -DBINDIR_PATH=\"$(bindir)\"
|
||||||
|
+ -DBINDIR_PATH=\"$(bindir)\" \
|
||||||
|
+ -DROOTSBINDIR_PATH=\"$(rootsbindir)\"
|
||||||
|
|
||||||
|
ifeq (,$(CXX))
|
||||||
|
LINKS_DSO_PROGRAM = links-dso-program-c
|
||||||
|
diff --git a/support/support.h b/support/support.h
|
||||||
|
index b162491..13076b7 100644
|
||||||
|
--- a/support/support.h
|
||||||
|
+++ b/support/support.h
|
||||||
|
@@ -107,6 +107,8 @@ extern const char support_install_prefix[];
|
||||||
|
extern const char support_libdir_prefix[];
|
||||||
|
/* Corresponds to the install's bin/ directory. */
|
||||||
|
extern const char support_bindir_prefix[];
|
||||||
|
+/* Corresponds to the install's sbin/ directory. */
|
||||||
|
+extern const char support_install_rootsbindir[];
|
||||||
|
|
||||||
|
extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *,
|
||||||
|
size_t, unsigned int);
|
||||||
|
diff --git a/support/support_paths.c b/support/support_paths.c
|
||||||
|
index 75634aa..1fe3283 100644
|
||||||
|
--- a/support/support_paths.c
|
||||||
|
+++ b/support/support_paths.c
|
||||||
|
@@ -64,3 +64,10 @@ const char support_bindir_prefix[] = BINDIR_PATH;
|
||||||
|
#else
|
||||||
|
# error please -DBINDIR_PATH=something in the Makefile
|
||||||
|
#endif
|
||||||
|
+
|
||||||
|
+#ifdef ROOTSBINDIR_PATH
|
||||||
|
+/* Corresponds to the install's sbin/ directory. */
|
||||||
|
+const char support_install_rootsbindir[] = ROOTSBINDIR_PATH;
|
||||||
|
+#else
|
||||||
|
+# error please -DROOTSBINDIR_PATH=something in the Makefile
|
||||||
|
+#endif
|
86
SOURCES/glibc-rh1747502-9.patch
Normal file
86
SOURCES/glibc-rh1747502-9.patch
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
From 304c61a24f909168c16793ccf7c686237e53d003 Mon Sep 17 00:00:00 2001
|
||||||
|
From: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Wed, 5 Dec 2018 12:39:47 -0500
|
||||||
|
Subject: test-container: move postclean outside of namespace changes
|
||||||
|
|
||||||
|
During postclean.req testing it was found that the fork in the
|
||||||
|
parent process (after the unshare syscall) would fail with ENOMEM
|
||||||
|
(see recursive_remove() in test-container.c). While failing with
|
||||||
|
ENOMEM is certainly unexpected, it is simply easier to refactor
|
||||||
|
the design and have the parent remain outside of the namespace.
|
||||||
|
This change moves the postclean.req processing to a distinct
|
||||||
|
process (the parent) that then forks the test process (which will
|
||||||
|
have to fork once more to complete uid/gid transitions). When the
|
||||||
|
test process exists the cleanup process will ensure all files are
|
||||||
|
deleted when a post clean is requested.
|
||||||
|
|
||||||
|
Signed-off-by: DJ Delorie <dj@redhat.com>
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
[BZ #23948]
|
||||||
|
* support/test-container.c: Move postclean step to before we
|
||||||
|
change namespaces.
|
||||||
|
|
||||||
|
diff --git a/support/test-container.c b/support/test-container.c
|
||||||
|
index df450adfdb..1d1aebeaf3 100644
|
||||||
|
--- a/support/test-container.c
|
||||||
|
+++ b/support/test-container.c
|
||||||
|
@@ -921,6 +921,43 @@ main (int argc, char **argv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (do_postclean)
|
||||||
|
+ {
|
||||||
|
+ pid_t pc_pid = fork ();
|
||||||
|
+
|
||||||
|
+ if (pc_pid < 0)
|
||||||
|
+ {
|
||||||
|
+ FAIL_EXIT1 ("Can't fork for post-clean");
|
||||||
|
+ }
|
||||||
|
+ else if (pc_pid > 0)
|
||||||
|
+ {
|
||||||
|
+ /* Parent. */
|
||||||
|
+ int status;
|
||||||
|
+ waitpid (pc_pid, &status, 0);
|
||||||
|
+
|
||||||
|
+ /* Child has exited, we can post-clean the test root. */
|
||||||
|
+ printf("running post-clean rsync\n");
|
||||||
|
+ rsync (pristine_root_path, new_root_path, 1);
|
||||||
|
+
|
||||||
|
+ if (WIFEXITED (status))
|
||||||
|
+ exit (WEXITSTATUS (status));
|
||||||
|
+
|
||||||
|
+ if (WIFSIGNALED (status))
|
||||||
|
+ {
|
||||||
|
+ printf ("%%SIGNALLED%%\n");
|
||||||
|
+ exit (77);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ printf ("%%EXITERROR%%\n");
|
||||||
|
+ exit (78);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Child continues. */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* This is the last point in the program where we're still in the
|
||||||
|
+ "normal" namespace. */
|
||||||
|
+
|
||||||
|
#ifdef CLONE_NEWNS
|
||||||
|
/* The unshare here gives us our own spaces and capabilities. */
|
||||||
|
if (unshare (CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS) < 0)
|
||||||
|
@@ -974,14 +1011,6 @@ main (int argc, char **argv)
|
||||||
|
int status;
|
||||||
|
waitpid (child, &status, 0);
|
||||||
|
|
||||||
|
- /* There's a bit of magic here, since the buildroot is mounted
|
||||||
|
- in our space, the paths are still valid, and since the mounts
|
||||||
|
- aren't recursive, it sees *only* the built root, not anything
|
||||||
|
- we would normally se if we rsync'd to "/" like mounted /dev
|
||||||
|
- files. */
|
||||||
|
- if (do_postclean)
|
||||||
|
- rsync (pristine_root_path, new_root_path, 1);
|
||||||
|
-
|
||||||
|
if (WIFEXITED (status))
|
||||||
|
exit (WEXITSTATUS (status));
|
||||||
|
|
268
SOURCES/glibc-rh1747502.patch
Normal file
268
SOURCES/glibc-rh1747502.patch
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
commit 99135114ba23c3110b7e4e650fabdc5e639746b7
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Fri Jun 28 18:30:00 2019 -0500
|
||||||
|
|
||||||
|
nss_db: fix endent wrt NULL mappings [BZ #24695] [BZ #24696]
|
||||||
|
|
||||||
|
nss_db allows for getpwent et al to be called without a set*ent,
|
||||||
|
but it only works once. After the last get*ent a set*ent is
|
||||||
|
required to restart, because the end*ent did not properly reset
|
||||||
|
the module. Resetting it to NULL allows for a proper restart.
|
||||||
|
|
||||||
|
If the database doesn't exist, however, end*ent erroniously called
|
||||||
|
munmap which set errno.
|
||||||
|
|
||||||
|
The test case runs "makedb" inside the testroot, so needs selinux
|
||||||
|
DSOs installed.
|
||||||
|
|
||||||
|
diff -rupN a/nss/Makefile b/nss/Makefile
|
||||||
|
--- a/nss/Makefile 2019-11-04 15:14:16.721221038 -0500
|
||||||
|
+++ b/nss/Makefile 2019-11-04 15:15:46.447544678 -0500
|
||||||
|
@@ -60,6 +60,10 @@ tests = test-netdb test-digits-dots ts
|
||||||
|
tst-nss-test5
|
||||||
|
xtests = bug-erange
|
||||||
|
|
||||||
|
+tests-container = \
|
||||||
|
+ tst-nss-db-endpwent \
|
||||||
|
+ tst-nss-db-endgrent
|
||||||
|
+
|
||||||
|
# Tests which need libdl
|
||||||
|
ifeq (yes,$(build-shared))
|
||||||
|
tests += tst-nss-files-hosts-erange
|
||||||
|
diff -rupN a/nss/nss_db/db-open.c b/nss/nss_db/db-open.c
|
||||||
|
--- a/nss/nss_db/db-open.c 2018-08-01 01:10:47.000000000 -0400
|
||||||
|
+++ b/nss/nss_db/db-open.c 2019-11-04 15:15:10.520213846 -0500
|
||||||
|
@@ -63,5 +63,9 @@ internal_setent (const char *file, struc
|
||||||
|
void
|
||||||
|
internal_endent (struct nss_db_map *mapping)
|
||||||
|
{
|
||||||
|
- munmap (mapping->header, mapping->len);
|
||||||
|
+ if (mapping->header != NULL)
|
||||||
|
+ {
|
||||||
|
+ munmap (mapping->header, mapping->len);
|
||||||
|
+ mapping->header = NULL;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
diff -rupN a/nss/tst-nss-db-endgrent.c b/nss/tst-nss-db-endgrent.c
|
||||||
|
--- a/nss/tst-nss-db-endgrent.c 1969-12-31 19:00:00.000000000 -0500
|
||||||
|
+++ b/nss/tst-nss-db-endgrent.c 2019-11-04 15:15:10.526214069 -0500
|
||||||
|
@@ -0,0 +1,54 @@
|
||||||
|
+/* Test for endgrent changing errno for BZ #24696
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <grp.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+
|
||||||
|
+/* The following test verifies that if the db NSS Service is initialized
|
||||||
|
+ with no database (getgrent), that a subsequent closure (endgrent) does
|
||||||
|
+ not set errno. In the case of the db service it is not an error to close
|
||||||
|
+ the service and so it should not set errno. */
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* Just make sure it's not there, although usually it won't be. */
|
||||||
|
+ unlink ("/var/db/group.db");
|
||||||
|
+
|
||||||
|
+ /* This, in conjunction with the testroot's nsswitch.conf, causes
|
||||||
|
+ the nss_db module to be "connected" and initialized - but the
|
||||||
|
+ testroot has no group.db, so no mapping will be created. */
|
||||||
|
+ getgrent ();
|
||||||
|
+
|
||||||
|
+ errno = 0;
|
||||||
|
+
|
||||||
|
+ /* Before the fix, this would call munmap (NULL) and set errno. */
|
||||||
|
+ endgrent ();
|
||||||
|
+
|
||||||
|
+ if (errno != 0)
|
||||||
|
+ FAIL_EXIT1 ("endgrent set errno to %d\n", errno);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff -rupN a/nss/tst-nss-db-endgrent.root/etc/nsswitch.conf b/nss/tst-nss-db-endgrent.root/etc/nsswitch.conf
|
||||||
|
--- a/nss/tst-nss-db-endgrent.root/etc/nsswitch.conf 1969-12-31 19:00:00.000000000 -0500
|
||||||
|
+++ b/nss/tst-nss-db-endgrent.root/etc/nsswitch.conf 2019-11-04 15:15:10.539214550 -0500
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+group : db files
|
||||||
|
diff -rupN a/nss/tst-nss-db-endpwent.c b/nss/tst-nss-db-endpwent.c
|
||||||
|
--- a/nss/tst-nss-db-endpwent.c 1969-12-31 19:00:00.000000000 -0500
|
||||||
|
+++ b/nss/tst-nss-db-endpwent.c 2019-11-04 15:15:10.545214772 -0500
|
||||||
|
@@ -0,0 +1,66 @@
|
||||||
|
+/* Test for endpwent->getpwent crash for BZ #24695
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <pwd.h>
|
||||||
|
+
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+
|
||||||
|
+/* It is entirely allowed to start with a getpwent call without
|
||||||
|
+ resetting the state of the service via a call to setpwent.
|
||||||
|
+ You can also call getpwent more times than you have entries in
|
||||||
|
+ the service, and it should not fail. This test iteratates the
|
||||||
|
+ database once, gets to the end, and then attempts a second
|
||||||
|
+ iteration to look for crashes. */
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+try_it (void)
|
||||||
|
+{
|
||||||
|
+ struct passwd *pw;
|
||||||
|
+
|
||||||
|
+ /* setpwent is intentionally omitted here. The first call to
|
||||||
|
+ getpwent detects that it's first and initializes. The second
|
||||||
|
+ time try_it is called, this "first call" was not detected before
|
||||||
|
+ the fix, and getpwent would crash. */
|
||||||
|
+
|
||||||
|
+ while ((pw = getpwent ()) != NULL)
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
+ /* We only care if this segfaults or not. */
|
||||||
|
+ endpwent ();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ char *cmd;
|
||||||
|
+
|
||||||
|
+ cmd = xasprintf ("%s/makedb -o /var/db/passwd.db /var/db/passwd.in",
|
||||||
|
+ support_bindir_prefix);
|
||||||
|
+ system (cmd);
|
||||||
|
+ free (cmd);
|
||||||
|
+
|
||||||
|
+ try_it ();
|
||||||
|
+ try_it ();
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff -rupN a/nss/tst-nss-db-endpwent.root/etc/nsswitch.conf b/nss/tst-nss-db-endpwent.root/etc/nsswitch.conf
|
||||||
|
--- a/nss/tst-nss-db-endpwent.root/etc/nsswitch.conf 1969-12-31 19:00:00.000000000 -0500
|
||||||
|
+++ b/nss/tst-nss-db-endpwent.root/etc/nsswitch.conf 2019-11-04 15:15:10.556215180 -0500
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+passwd: db
|
||||||
|
diff -rupN a/nss/tst-nss-db-endpwent.root/var/db/passwd.in b/nss/tst-nss-db-endpwent.root/var/db/passwd.in
|
||||||
|
--- a/nss/tst-nss-db-endpwent.root/var/db/passwd.in 1969-12-31 19:00:00.000000000 -0500
|
||||||
|
+++ b/nss/tst-nss-db-endpwent.root/var/db/passwd.in 2019-11-04 15:15:10.567215588 -0500
|
||||||
|
@@ -0,0 +1,4 @@
|
||||||
|
+.root root:x:0:0:root:/root:/bin/bash
|
||||||
|
+=0 root:x:0:0:root:/root:/bin/bash
|
||||||
|
+.bin bin:x:1:1:bin:/bin:/sbin/nologin
|
||||||
|
+=1 bin:x:1:1:bin:/bin:/sbin/nologin
|
||||||
|
diff -rupN a/support/Makefile b/support/Makefile
|
||||||
|
--- a/support/Makefile 2019-11-04 15:14:20.416357911 -0500
|
||||||
|
+++ b/support/Makefile 2019-11-04 15:15:10.574215847 -0500
|
||||||
|
@@ -180,6 +180,11 @@ LINKS_DSO_PROGRAM = links-dso-program
|
||||||
|
LDLIBS-links-dso-program = -lstdc++ -lgcc -lgcc_s $(libunwind)
|
||||||
|
endif
|
||||||
|
|
||||||
|
+ifeq (yes,$(have-selinux))
|
||||||
|
+LDLIBS-$(LINKS_DSO_PROGRAM) += -lselinux
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
+
|
||||||
|
LDLIBS-test-container = $(libsupport)
|
||||||
|
|
||||||
|
others += test-container
|
||||||
|
diff -rupN a/support/links-dso-program-c.c b/support/links-dso-program-c.c
|
||||||
|
--- a/support/links-dso-program-c.c 2019-11-04 15:14:17.073234077 -0500
|
||||||
|
+++ b/support/links-dso-program-c.c 2019-11-04 15:15:10.580216069 -0500
|
||||||
|
@@ -1,9 +1,26 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
+/* makedb needs selinux dso's. */
|
||||||
|
+#ifdef HAVE_SELINUX
|
||||||
|
+# include <selinux/selinux.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+/* The purpose of this file is to indicate to the build system which
|
||||||
|
+ shared objects need to be copied into the testroot, such as gcc or
|
||||||
|
+ selinux support libraries. This program is never executed, only
|
||||||
|
+ scanned for dependencies on shared objects, so the code below may
|
||||||
|
+ seem weird - it's written to survive gcc optimization and force
|
||||||
|
+ such dependencies.
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Complexity to keep gcc from optimizing this away. */
|
||||||
|
printf ("This is a test %s.\n", argc > 1 ? argv[1] : "null");
|
||||||
|
+#ifdef HAVE_SELINUX
|
||||||
|
+ /* This exists to force libselinux.so to be required. */
|
||||||
|
+ printf ("selinux %d\n", is_selinux_enabled ());
|
||||||
|
+#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff -rupN a/support/links-dso-program.cc b/support/links-dso-program.cc
|
||||||
|
--- a/support/links-dso-program.cc 2019-11-04 15:14:17.079234300 -0500
|
||||||
|
+++ b/support/links-dso-program.cc 2019-11-04 15:15:10.587216328 -0500
|
||||||
|
@@ -1,11 +1,28 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
+/* makedb needs selinux dso's. */
|
||||||
|
+#ifdef HAVE_SELINUX
|
||||||
|
+# include <selinux/selinux.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
+/* The purpose of this file is to indicate to the build system which
|
||||||
|
+ shared objects need to be copied into the testroot, such as gcc or
|
||||||
|
+ selinux support libraries. This program is never executed, only
|
||||||
|
+ scanned for dependencies on shared objects, so the code below may
|
||||||
|
+ seem weird - it's written to survive gcc optimization and force
|
||||||
|
+ such dependencies.
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Complexity to keep gcc from optimizing this away. */
|
||||||
|
cout << (argc > 1 ? argv[1] : "null");
|
||||||
|
+#ifdef HAVE_SELINUX
|
||||||
|
+ /* This exists to force libselinux.so to be required. */
|
||||||
|
+ cout << "selinux " << is_selinux_enabled ();
|
||||||
|
+#endif
|
||||||
|
return 0;
|
||||||
|
}
|
196
SOURCES/glibc-rh1747505-1.patch
Normal file
196
SOURCES/glibc-rh1747505-1.patch
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
commit 4b7c74179c8928d971d370e1137d202f891a4cf5
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Wed Mar 20 12:40:18 2019 -0400
|
||||||
|
|
||||||
|
nss: Make nsswitch.conf more distribution friendly.
|
||||||
|
|
||||||
|
The current default nsswitch.conf file provided by glibc is not very
|
||||||
|
distribution friendly. The file contains some minimal directives that no
|
||||||
|
real distribution uses. This update aims to provide a rich set of
|
||||||
|
comments which are useful for all distributions, and a broader set of
|
||||||
|
service defines which should work for all distributions.
|
||||||
|
|
||||||
|
Tested defaults on x86_64 and they work. The nsswitch.conf file more
|
||||||
|
closely matches what we have in Fedora now, and I'll adjust Fedora to
|
||||||
|
use this version with minor changes to enable Fedora-specific service
|
||||||
|
providers.
|
||||||
|
|
||||||
|
v2
|
||||||
|
- Add missing databases to manual.
|
||||||
|
- Add link to manual from default nsswitch.conf.
|
||||||
|
- Sort nsswitch.conf according to most used database first.
|
||||||
|
|
||||||
|
v3
|
||||||
|
- Only mention implemented services in 'NSS Basics.'
|
||||||
|
- Mention 'automount' in 'Services in the NSS configuration.'
|
||||||
|
- Sort services in alphabetical order.
|
||||||
|
|
||||||
|
v4
|
||||||
|
- Project name is 'Samba'.
|
||||||
|
|
||||||
|
v5
|
||||||
|
- Fix typo in manual/nss.texi.
|
||||||
|
|
||||||
|
v6
|
||||||
|
- Fix another typo in manual/nss.texi. Ran spell checker this time.
|
||||||
|
|
||||||
|
diff --git a/manual/nss.texi b/manual/nss.texi
|
||||||
|
index 164ae33246..821469a78a 100644
|
||||||
|
--- a/manual/nss.texi
|
||||||
|
+++ b/manual/nss.texi
|
||||||
|
@@ -56,13 +56,17 @@ functions to access the databases.
|
||||||
|
@noindent
|
||||||
|
The databases available in the NSS are
|
||||||
|
|
||||||
|
+@cindex aliases
|
||||||
|
@cindex ethers
|
||||||
|
@cindex group
|
||||||
|
+@cindex gshadow
|
||||||
|
@cindex hosts
|
||||||
|
+@cindex initgroups
|
||||||
|
@cindex netgroup
|
||||||
|
@cindex networks
|
||||||
|
-@cindex protocols
|
||||||
|
@cindex passwd
|
||||||
|
+@cindex protocols
|
||||||
|
+@cindex publickey
|
||||||
|
@cindex rpc
|
||||||
|
@cindex services
|
||||||
|
@cindex shadow
|
||||||
|
@@ -75,16 +79,22 @@ Ethernet numbers,
|
||||||
|
@comment @pxref{Ethernet Numbers}.
|
||||||
|
@item group
|
||||||
|
Groups of users, @pxref{Group Database}.
|
||||||
|
+@item gshadow
|
||||||
|
+Group passphrase hashes and related information.
|
||||||
|
@item hosts
|
||||||
|
Host names and numbers, @pxref{Host Names}.
|
||||||
|
+@item initgroups
|
||||||
|
+Supplementary group access list.
|
||||||
|
@item netgroup
|
||||||
|
Network wide list of host and users, @pxref{Netgroup Database}.
|
||||||
|
@item networks
|
||||||
|
Network names and numbers, @pxref{Networks Database}.
|
||||||
|
-@item protocols
|
||||||
|
-Network protocols, @pxref{Protocols Database}.
|
||||||
|
@item passwd
|
||||||
|
User identities, @pxref{User Database}.
|
||||||
|
+@item protocols
|
||||||
|
+Network protocols, @pxref{Protocols Database}.
|
||||||
|
+@item publickey
|
||||||
|
+Public keys for Secure RPC.
|
||||||
|
@item rpc
|
||||||
|
Remote procedure call names and numbers.
|
||||||
|
@comment @pxref{RPC Database}.
|
||||||
|
@@ -96,8 +106,8 @@ User passphrase hashes and related information.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
-There will be some more added later (@code{automount}, @code{bootparams},
|
||||||
|
-@code{netmasks}, and @code{publickey}).
|
||||||
|
+@c We currently don't implement automount, netmasks, or bootparams.
|
||||||
|
+More databases may be added later.
|
||||||
|
|
||||||
|
@node NSS Configuration File, NSS Module Internals, NSS Basics, Name Service Switch
|
||||||
|
@section The NSS Configuration File
|
||||||
|
@@ -159,6 +169,10 @@ these files since they should be placed in a directory where they are
|
||||||
|
found automatically. Only the names of all available services are
|
||||||
|
important.
|
||||||
|
|
||||||
|
+Lastly, some system software may make use of the NSS configuration file
|
||||||
|
+to store their own configuration for similar purposes. Examples of this
|
||||||
|
+include the @code{automount} service which is used by @code{autofs}.
|
||||||
|
+
|
||||||
|
@node Actions in the NSS configuration, Notes on NSS Configuration File, Services in the NSS configuration, NSS Configuration File
|
||||||
|
@subsection Actions in the NSS configuration
|
||||||
|
|
||||||
|
diff --git a/nss/nsswitch.conf b/nss/nsswitch.conf
|
||||||
|
index 39ca88bf51..f553588114 100644
|
||||||
|
--- a/nss/nsswitch.conf
|
||||||
|
+++ b/nss/nsswitch.conf
|
||||||
|
@@ -1,20 +1,69 @@
|
||||||
|
+#
|
||||||
|
# /etc/nsswitch.conf
|
||||||
|
#
|
||||||
|
-# Example configuration of GNU Name Service Switch functionality.
|
||||||
|
+# An example Name Service Switch config file. This file should be
|
||||||
|
+# sorted with the most-used services at the beginning.
|
||||||
|
#
|
||||||
|
+# Valid databases are: aliases, ethers, group, gshadow, hosts,
|
||||||
|
+# initgroups, netgroup, networks, passwd, protocols, publickey,
|
||||||
|
+# rpc, services, and shadow.
|
||||||
|
+#
|
||||||
|
+# Valid service provider entries include (in alphabetical order):
|
||||||
|
+#
|
||||||
|
+# compat Use /etc files plus *_compat pseudo-db
|
||||||
|
+# db Use the pre-processed /var/db files
|
||||||
|
+# dns Use DNS (Domain Name Service)
|
||||||
|
+# files Use the local files in /etc
|
||||||
|
+# hesiod Use Hesiod (DNS) for user lookups
|
||||||
|
+# nis Use NIS (NIS version 2), also called YP
|
||||||
|
+# nisplus Use NIS+ (NIS version 3)
|
||||||
|
+#
|
||||||
|
+# See `info libc 'NSS Basics'` for more information.
|
||||||
|
+#
|
||||||
|
+# Commonly used alternative service providers (may need installation):
|
||||||
|
+#
|
||||||
|
+# ldap Use LDAP directory server
|
||||||
|
+# myhostname Use systemd host names
|
||||||
|
+# mymachines Use systemd machine names
|
||||||
|
+# mdns*, mdns*_minimal Use Avahi mDNS/DNS-SD
|
||||||
|
+# resolve Use systemd resolved resolver
|
||||||
|
+# sss Use System Security Services Daemon (sssd)
|
||||||
|
+# systemd Use systemd for dynamic user option
|
||||||
|
+# winbind Use Samba winbind support
|
||||||
|
+# wins Use Samba wins support
|
||||||
|
+# wrapper Use wrapper module for testing
|
||||||
|
+#
|
||||||
|
+# Notes:
|
||||||
|
+#
|
||||||
|
+# 'sssd' performs its own 'files'-based caching, so it should generally
|
||||||
|
+# come before 'files'.
|
||||||
|
+#
|
||||||
|
+# WARNING: Running nscd with a secondary caching service like sssd may
|
||||||
|
+# lead to unexpected behaviour, especially with how long
|
||||||
|
+# entries are cached.
|
||||||
|
+#
|
||||||
|
+# Installation instructions:
|
||||||
|
+#
|
||||||
|
+# To use 'db', install the appropriate package(s) (provide 'makedb' and
|
||||||
|
+# libnss_db.so.*), and place the 'db' in front of 'files' for entries
|
||||||
|
+# you want to be looked up first in the databases, like this:
|
||||||
|
+#
|
||||||
|
+# passwd: db files
|
||||||
|
+# shadow: db files
|
||||||
|
+# group: db files
|
||||||
|
|
||||||
|
-passwd: db files
|
||||||
|
-group: db files
|
||||||
|
-initgroups: db [SUCCESS=continue] files
|
||||||
|
-shadow: db files
|
||||||
|
-gshadow: files
|
||||||
|
-
|
||||||
|
-hosts: files dns
|
||||||
|
-networks: files dns
|
||||||
|
-
|
||||||
|
-protocols: db files
|
||||||
|
-services: db files
|
||||||
|
-ethers: db files
|
||||||
|
-rpc: db files
|
||||||
|
-
|
||||||
|
-netgroup: db files
|
||||||
|
+# In alphabetical order. Re-order as required to optimize peformance.
|
||||||
|
+aliases: files
|
||||||
|
+ethers: files
|
||||||
|
+group: files
|
||||||
|
+gshadow: files
|
||||||
|
+hosts: files dns
|
||||||
|
+initgroups: files
|
||||||
|
+netgroup: files
|
||||||
|
+networks: files dns
|
||||||
|
+passwd: files
|
||||||
|
+protocols: files
|
||||||
|
+publickey: files
|
||||||
|
+rpc: files
|
||||||
|
+shadow: files
|
||||||
|
+services: files
|
38
SOURCES/glibc-rh1747505-2.patch
Normal file
38
SOURCES/glibc-rh1747505-2.patch
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
commit d34d4c80226b3f5a1b51a8e5b005a52fba07d7ba
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Wed Mar 20 22:11:32 2019 -0400
|
||||||
|
|
||||||
|
nscd: Improve nscd.conf comments.
|
||||||
|
|
||||||
|
This change adds a warning to nscd.conf about running multiple caching
|
||||||
|
services together and that it may lead to unexpected behaviours. Also we
|
||||||
|
add a note that enabling the 'shared' option will cause cache hit rates
|
||||||
|
to be misreported (a side effect of the implementation).
|
||||||
|
|
||||||
|
v2
|
||||||
|
- Rewrite comment to avoid implementation details.
|
||||||
|
|
||||||
|
diff --git a/nscd/nscd.conf b/nscd/nscd.conf
|
||||||
|
index 39b875912d..487ffe461d 100644
|
||||||
|
--- a/nscd/nscd.conf
|
||||||
|
+++ b/nscd/nscd.conf
|
||||||
|
@@ -3,6 +3,9 @@
|
||||||
|
#
|
||||||
|
# An example Name Service Cache config file. This file is needed by nscd.
|
||||||
|
#
|
||||||
|
+# WARNING: Running nscd with a secondary caching service like sssd may lead to
|
||||||
|
+# unexpected behaviour, especially with how long entries are cached.
|
||||||
|
+#
|
||||||
|
# Legal entries are:
|
||||||
|
#
|
||||||
|
# logfile <file>
|
||||||
|
@@ -23,6 +26,9 @@
|
||||||
|
# check-files <service> <yes|no>
|
||||||
|
# persistent <service> <yes|no>
|
||||||
|
# shared <service> <yes|no>
|
||||||
|
+# NOTE: Setting 'shared' to a value of 'yes' will accelerate the lookup,
|
||||||
|
+# but those lookups will not be counted as cache hits
|
||||||
|
+# i.e. 'nscd -g' may show '0%'.
|
||||||
|
# max-db-size <service> <number bytes>
|
||||||
|
# auto-propagate <service> <yes|no>
|
||||||
|
#
|
40
SOURCES/glibc-rh1747505-3.patch
Normal file
40
SOURCES/glibc-rh1747505-3.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
diff -Nrup a/nss/nsswitch.conf b/nss/nsswitch.conf
|
||||||
|
--- a/nss/nsswitch.conf 2019-10-25 12:14:09.255834866 -0400
|
||||||
|
+++ b/nss/nsswitch.conf 2019-10-25 12:50:08.425769248 -0400
|
||||||
|
@@ -1,7 +1,7 @@
|
||||||
|
#
|
||||||
|
# /etc/nsswitch.conf
|
||||||
|
#
|
||||||
|
-# An example Name Service Switch config file. This file should be
|
||||||
|
+# Name Service Switch config file. This file should be
|
||||||
|
# sorted with the most-used services at the beginning.
|
||||||
|
#
|
||||||
|
# Valid databases are: aliases, ethers, group, gshadow, hosts,
|
||||||
|
@@ -52,18 +52,20 @@
|
||||||
|
# shadow: db files
|
||||||
|
# group: db files
|
||||||
|
|
||||||
|
-# In alphabetical order. Re-order as required to optimize peformance.
|
||||||
|
+# In order of likelihood of use to accelerate lookup.
|
||||||
|
+passwd: sss files
|
||||||
|
+shadow: files sss
|
||||||
|
+group: sss files
|
||||||
|
+hosts: files dns myhostname
|
||||||
|
+services: files sss
|
||||||
|
+netgroup: sss
|
||||||
|
+automount: files sss
|
||||||
|
+
|
||||||
|
aliases: files
|
||||||
|
ethers: files
|
||||||
|
-group: files
|
||||||
|
gshadow: files
|
||||||
|
-hosts: files dns
|
||||||
|
initgroups: files
|
||||||
|
-netgroup: files
|
||||||
|
networks: files dns
|
||||||
|
-passwd: files
|
||||||
|
protocols: files
|
||||||
|
publickey: files
|
||||||
|
rpc: files
|
||||||
|
-shadow: files
|
||||||
|
-services: files
|
27
SOURCES/glibc-rh1747505-4.patch
Normal file
27
SOURCES/glibc-rh1747505-4.patch
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
commit eed1f6fcdb0526498223ebfe95f91ef5dec2172a
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Tue Oct 29 11:58:03 2019 -0400
|
||||||
|
|
||||||
|
Comment out initgroups from example nsswitch.conf (Bug 25146)
|
||||||
|
|
||||||
|
In commit 4b7c74179c8928d971d370e1137d202f891a4cf5 the nsswitch.conf
|
||||||
|
file was harmonized with downstream distributions, but this change
|
||||||
|
included adding "initgroups: files". We should not add initgroups by
|
||||||
|
default, we can have it, but it should be commented out to allow it
|
||||||
|
to inherit the settings for group. The problem is principally that
|
||||||
|
downstream authconfig won't update initgroups and it will get out of
|
||||||
|
sync with the setting for group.
|
||||||
|
|
||||||
|
diff -Nrup a/nss/nsswitch.conf b/nss/nsswitch.conf
|
||||||
|
--- a/nss/nsswitch.conf 2019-10-29 14:13:15.883199544 -0400
|
||||||
|
+++ b/nss/nsswitch.conf 2019-10-29 14:15:44.860978858 -0400
|
||||||
|
@@ -64,7 +64,8 @@ automount: files sss
|
||||||
|
aliases: files
|
||||||
|
ethers: files
|
||||||
|
gshadow: files
|
||||||
|
-initgroups: files
|
||||||
|
+# Allow initgroups to default to the setting for group.
|
||||||
|
+# initgroups: files
|
||||||
|
networks: files dns
|
||||||
|
protocols: files
|
||||||
|
publickey: files
|
512
SOURCES/glibc-rh1749439-1.patch
Normal file
512
SOURCES/glibc-rh1749439-1.patch
Normal file
@ -0,0 +1,512 @@
|
|||||||
|
commit 1a7fe2ebe52b3c8bf465d1756e69452d05c1c103
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon Aug 5 15:54:10 2019 +0200
|
||||||
|
|
||||||
|
login: Remove utmp backend jump tables [BZ #23518]
|
||||||
|
|
||||||
|
There is just one file-based implementation, so this dispatch
|
||||||
|
mechanism is unnecessary. Instead of the vtable pointer
|
||||||
|
__libc_utmp_jump_table, use a non-negative file_fd as the indicator
|
||||||
|
that the backend is initialized.
|
||||||
|
|
||||||
|
diff --git a/login/getutent_r.c b/login/getutent_r.c
|
||||||
|
index 6a244ba6e0b86da7..44239ecb81bacea4 100644
|
||||||
|
--- a/login/getutent_r.c
|
||||||
|
+++ b/login/getutent_r.c
|
||||||
|
@@ -23,115 +23,16 @@
|
||||||
|
|
||||||
|
#include "utmp-private.h"
|
||||||
|
|
||||||
|
-
|
||||||
|
-/* Functions defined here. */
|
||||||
|
-static int setutent_unknown (void);
|
||||||
|
-static int getutent_r_unknown (struct utmp *buffer, struct utmp **result);
|
||||||
|
-static int getutid_r_unknown (const struct utmp *line, struct utmp *buffer,
|
||||||
|
- struct utmp **result);
|
||||||
|
-static int getutline_r_unknown (const struct utmp *id, struct utmp *buffer,
|
||||||
|
- struct utmp **result);
|
||||||
|
-static struct utmp *pututline_unknown (const struct utmp *data);
|
||||||
|
-static void endutent_unknown (void);
|
||||||
|
-
|
||||||
|
-/* Initial Jump table. */
|
||||||
|
-const struct utfuncs __libc_utmp_unknown_functions =
|
||||||
|
-{
|
||||||
|
- setutent_unknown,
|
||||||
|
- getutent_r_unknown,
|
||||||
|
- getutid_r_unknown,
|
||||||
|
- getutline_r_unknown,
|
||||||
|
- pututline_unknown,
|
||||||
|
- endutent_unknown,
|
||||||
|
- NULL
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-/* Currently selected backend. */
|
||||||
|
-const struct utfuncs *__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
|
||||||
|
-
|
||||||
|
/* We need to protect the opening of the file. */
|
||||||
|
__libc_lock_define_initialized (, __libc_utmp_lock attribute_hidden)
|
||||||
|
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-setutent_unknown (void)
|
||||||
|
-{
|
||||||
|
- int result;
|
||||||
|
-
|
||||||
|
- result = (*__libc_utmp_file_functions.setutent) ();
|
||||||
|
- if (result)
|
||||||
|
- __libc_utmp_jump_table = &__libc_utmp_file_functions;
|
||||||
|
-
|
||||||
|
- return result;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static int
|
||||||
|
-getutent_r_unknown (struct utmp *buffer, struct utmp **result)
|
||||||
|
-{
|
||||||
|
- /* The backend was not yet initialized. */
|
||||||
|
- if (setutent_unknown ())
|
||||||
|
- return (*__libc_utmp_jump_table->getutent_r) (buffer, result);
|
||||||
|
-
|
||||||
|
- /* Not available. */
|
||||||
|
- *result = NULL;
|
||||||
|
- return -1;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static int
|
||||||
|
-getutid_r_unknown (const struct utmp *id, struct utmp *buffer,
|
||||||
|
- struct utmp **result)
|
||||||
|
-{
|
||||||
|
- /* The backend was not yet initialized. */
|
||||||
|
- if (setutent_unknown ())
|
||||||
|
- return (*__libc_utmp_jump_table->getutid_r) (id, buffer, result);
|
||||||
|
-
|
||||||
|
- /* Not available. */
|
||||||
|
- *result = NULL;
|
||||||
|
- return -1;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static int
|
||||||
|
-getutline_r_unknown (const struct utmp *line, struct utmp *buffer,
|
||||||
|
- struct utmp **result)
|
||||||
|
-{
|
||||||
|
- /* The backend was not yet initialized. */
|
||||||
|
- if (setutent_unknown ())
|
||||||
|
- return (*__libc_utmp_jump_table->getutline_r) (line, buffer, result);
|
||||||
|
-
|
||||||
|
- /* Not available. */
|
||||||
|
- *result = NULL;
|
||||||
|
- return -1;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static struct utmp *
|
||||||
|
-pututline_unknown (const struct utmp *data)
|
||||||
|
-{
|
||||||
|
- /* The backend was not yet initialized. */
|
||||||
|
- if (setutent_unknown ())
|
||||||
|
- return (*__libc_utmp_jump_table->pututline) (data);
|
||||||
|
-
|
||||||
|
- /* Not available. */
|
||||||
|
- return NULL;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-endutent_unknown (void)
|
||||||
|
-{
|
||||||
|
- /* Nothing to do. */
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
void
|
||||||
|
__setutent (void)
|
||||||
|
{
|
||||||
|
__libc_lock_lock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
- (*__libc_utmp_jump_table->setutent) ();
|
||||||
|
+ __libc_setutent ();
|
||||||
|
|
||||||
|
__libc_lock_unlock (__libc_utmp_lock);
|
||||||
|
}
|
||||||
|
@@ -145,7 +46,7 @@ __getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
|
||||||
|
__libc_lock_lock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
- retval = (*__libc_utmp_jump_table->getutent_r) (buffer, result);
|
||||||
|
+ retval = __libc_getutent_r (buffer, result);
|
||||||
|
|
||||||
|
__libc_lock_unlock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
@@ -162,7 +63,7 @@ __pututline (const struct utmp *data)
|
||||||
|
|
||||||
|
__libc_lock_lock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
- buffer = (*__libc_utmp_jump_table->pututline) (data);
|
||||||
|
+ buffer = __libc_pututline (data);
|
||||||
|
|
||||||
|
__libc_lock_unlock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
@@ -177,8 +78,7 @@ __endutent (void)
|
||||||
|
{
|
||||||
|
__libc_lock_lock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
- (*__libc_utmp_jump_table->endutent) ();
|
||||||
|
- __libc_utmp_jump_table = &__libc_utmp_unknown_functions;
|
||||||
|
+ __libc_endutent ();
|
||||||
|
|
||||||
|
__libc_lock_unlock (__libc_utmp_lock);
|
||||||
|
}
|
||||||
|
diff --git a/login/getutid_r.c b/login/getutid_r.c
|
||||||
|
index b7d3dbac75774b0a..8cb6b16d735e8265 100644
|
||||||
|
--- a/login/getutid_r.c
|
||||||
|
+++ b/login/getutid_r.c
|
||||||
|
@@ -49,7 +49,7 @@ __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result)
|
||||||
|
|
||||||
|
__libc_lock_lock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
- retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result);
|
||||||
|
+ retval = __libc_getutid_r (id, buffer, result);
|
||||||
|
|
||||||
|
__libc_lock_unlock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
diff --git a/login/getutline_r.c b/login/getutline_r.c
|
||||||
|
index 6996887f76b28816..5607c19ed2e1ca66 100644
|
||||||
|
--- a/login/getutline_r.c
|
||||||
|
+++ b/login/getutline_r.c
|
||||||
|
@@ -36,7 +36,7 @@ __getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
|
||||||
|
__libc_lock_lock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
- retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result);
|
||||||
|
+ retval = __libc_getutline_r (line, buffer, result);
|
||||||
|
|
||||||
|
__libc_lock_unlock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
diff --git a/login/updwtmp.c b/login/updwtmp.c
|
||||||
|
index 56fb41916a776c0a..7ae96224ca789b6d 100644
|
||||||
|
--- a/login/updwtmp.c
|
||||||
|
+++ b/login/updwtmp.c
|
||||||
|
@@ -29,7 +29,7 @@ __updwtmp (const char *wtmp_file, const struct utmp *utmp)
|
||||||
|
{
|
||||||
|
const char *file_name = TRANSFORM_UTMP_FILE_NAME (wtmp_file);
|
||||||
|
|
||||||
|
- (*__libc_utmp_file_functions.updwtmp) (file_name, utmp);
|
||||||
|
+ __libc_updwtmp (file_name, utmp);
|
||||||
|
}
|
||||||
|
libc_hidden_def (__updwtmp)
|
||||||
|
weak_alias (__updwtmp, updwtmp)
|
||||||
|
diff --git a/login/utmp-private.h b/login/utmp-private.h
|
||||||
|
index bd8773984cfc56de..5c2048ee52dc3cee 100644
|
||||||
|
--- a/login/utmp-private.h
|
||||||
|
+++ b/login/utmp-private.h
|
||||||
|
@@ -24,24 +24,17 @@
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <libc-lock.h>
|
||||||
|
|
||||||
|
-/* The structure describing the functions in a backend. */
|
||||||
|
-struct utfuncs
|
||||||
|
-{
|
||||||
|
- int (*setutent) (void);
|
||||||
|
- int (*getutent_r) (struct utmp *, struct utmp **);
|
||||||
|
- int (*getutid_r) (const struct utmp *, struct utmp *, struct utmp **);
|
||||||
|
- int (*getutline_r) (const struct utmp *, struct utmp *, struct utmp **);
|
||||||
|
- struct utmp *(*pututline) (const struct utmp *);
|
||||||
|
- void (*endutent) (void);
|
||||||
|
- int (*updwtmp) (const char *, const struct utmp *);
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-/* The tables from the services. */
|
||||||
|
-extern const struct utfuncs __libc_utmp_file_functions attribute_hidden;
|
||||||
|
-extern const struct utfuncs __libc_utmp_unknown_functions attribute_hidden;
|
||||||
|
-
|
||||||
|
-/* Currently selected backend. */
|
||||||
|
-extern const struct utfuncs *__libc_utmp_jump_table attribute_hidden;
|
||||||
|
+/* These functions check for initialization, but not perform any
|
||||||
|
+ locking. */
|
||||||
|
+int __libc_setutent (void) attribute_hidden;
|
||||||
|
+int __libc_getutent_r (struct utmp *, struct utmp **) attribute_hidden;
|
||||||
|
+int __libc_getutid_r (const struct utmp *, struct utmp *, struct utmp **)
|
||||||
|
+ attribute_hidden;
|
||||||
|
+int __libc_getutline_r (const struct utmp *, struct utmp *, struct utmp **)
|
||||||
|
+ attribute_hidden;
|
||||||
|
+struct utmp *__libc_pututline (const struct utmp *) attribute_hidden;
|
||||||
|
+void __libc_endutent (void) attribute_hidden;
|
||||||
|
+int __libc_updwtmp (const char *, const struct utmp *) attribute_hidden;
|
||||||
|
|
||||||
|
/* Current file name. */
|
||||||
|
extern const char *__libc_utmp_file_name attribute_hidden;
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index 040a5057116bb69d..069e6d0452e333ad 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -105,37 +105,12 @@ static void timeout_handler (int signum) {};
|
||||||
|
alarm (old_timeout); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
-
|
||||||
|
-/* Functions defined here. */
|
||||||
|
-static int setutent_file (void);
|
||||||
|
-static int getutent_r_file (struct utmp *buffer, struct utmp **result);
|
||||||
|
-static int getutid_r_file (const struct utmp *key, struct utmp *buffer,
|
||||||
|
- struct utmp **result);
|
||||||
|
-static int getutline_r_file (const struct utmp *key, struct utmp *buffer,
|
||||||
|
- struct utmp **result);
|
||||||
|
-static struct utmp *pututline_file (const struct utmp *data);
|
||||||
|
-static void endutent_file (void);
|
||||||
|
-static int updwtmp_file (const char *file, const struct utmp *utmp);
|
||||||
|
-
|
||||||
|
-/* Jump table for file functions. */
|
||||||
|
-const struct utfuncs __libc_utmp_file_functions =
|
||||||
|
-{
|
||||||
|
- setutent_file,
|
||||||
|
- getutent_r_file,
|
||||||
|
- getutid_r_file,
|
||||||
|
- getutline_r_file,
|
||||||
|
- pututline_file,
|
||||||
|
- endutent_file,
|
||||||
|
- updwtmp_file
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-
|
||||||
|
#ifndef TRANSFORM_UTMP_FILE_NAME
|
||||||
|
# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-setutent_file (void)
|
||||||
|
+int
|
||||||
|
+__libc_setutent (void)
|
||||||
|
{
|
||||||
|
if (file_fd < 0)
|
||||||
|
{
|
||||||
|
@@ -166,15 +141,19 @@ setutent_file (void)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Preform initialization if necessary. */
|
||||||
|
+static bool
|
||||||
|
+maybe_setutent (void)
|
||||||
|
+{
|
||||||
|
+ return file_fd >= 0 || __libc_setutent ();
|
||||||
|
+}
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-getutent_r_file (struct utmp *buffer, struct utmp **result)
|
||||||
|
+int
|
||||||
|
+__libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
{
|
||||||
|
ssize_t nbytes;
|
||||||
|
|
||||||
|
- assert (file_fd >= 0);
|
||||||
|
-
|
||||||
|
- if (file_offset == -1l)
|
||||||
|
+ if (!maybe_setutent () || file_offset == -1l)
|
||||||
|
{
|
||||||
|
/* Not available. */
|
||||||
|
*result = NULL;
|
||||||
|
@@ -279,13 +258,11 @@ unlock_return:
|
||||||
|
|
||||||
|
/* For implementing this function we don't use the getutent_r function
|
||||||
|
because we can avoid the reposition on every new entry this way. */
|
||||||
|
-static int
|
||||||
|
-getutid_r_file (const struct utmp *id, struct utmp *buffer,
|
||||||
|
- struct utmp **result)
|
||||||
|
+int
|
||||||
|
+__libc_getutid_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
+ struct utmp **result)
|
||||||
|
{
|
||||||
|
- assert (file_fd >= 0);
|
||||||
|
-
|
||||||
|
- if (file_offset == -1l)
|
||||||
|
+ if (!maybe_setutent () || file_offset == -1l)
|
||||||
|
{
|
||||||
|
*result = NULL;
|
||||||
|
return -1;
|
||||||
|
@@ -309,13 +286,11 @@ getutid_r_file (const struct utmp *id, struct utmp *buffer,
|
||||||
|
|
||||||
|
/* For implementing this function we don't use the getutent_r function
|
||||||
|
because we can avoid the reposition on every new entry this way. */
|
||||||
|
-static int
|
||||||
|
-getutline_r_file (const struct utmp *line, struct utmp *buffer,
|
||||||
|
- struct utmp **result)
|
||||||
|
+int
|
||||||
|
+__libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
+ struct utmp **result)
|
||||||
|
{
|
||||||
|
- assert (file_fd >= 0);
|
||||||
|
-
|
||||||
|
- if (file_offset == -1l)
|
||||||
|
+ if (!maybe_setutent () || file_offset == -1l)
|
||||||
|
{
|
||||||
|
*result = NULL;
|
||||||
|
return -1;
|
||||||
|
@@ -361,15 +336,16 @@ unlock_return:
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static struct utmp *
|
||||||
|
-pututline_file (const struct utmp *data)
|
||||||
|
+struct utmp *
|
||||||
|
+__libc_pututline (const struct utmp *data)
|
||||||
|
{
|
||||||
|
+ if (!maybe_setutent ())
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
struct utmp buffer;
|
||||||
|
struct utmp *pbuf;
|
||||||
|
int found;
|
||||||
|
|
||||||
|
- assert (file_fd >= 0);
|
||||||
|
-
|
||||||
|
if (! file_writable)
|
||||||
|
{
|
||||||
|
/* We must make the file descriptor writable before going on. */
|
||||||
|
@@ -467,18 +443,19 @@ pututline_file (const struct utmp *data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-endutent_file (void)
|
||||||
|
+void
|
||||||
|
+__libc_endutent (void)
|
||||||
|
{
|
||||||
|
- assert (file_fd >= 0);
|
||||||
|
-
|
||||||
|
- __close_nocancel_nostatus (file_fd);
|
||||||
|
- file_fd = -1;
|
||||||
|
+ if (file_fd >= 0)
|
||||||
|
+ {
|
||||||
|
+ __close_nocancel_nostatus (file_fd);
|
||||||
|
+ file_fd = -1;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-updwtmp_file (const char *file, const struct utmp *utmp)
|
||||||
|
+int
|
||||||
|
+__libc_updwtmp (const char *file, const struct utmp *utmp)
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
off64_t offset;
|
||||||
|
diff --git a/login/utmpname.c b/login/utmpname.c
|
||||||
|
index 21cb890a1a2fdc92..73b19c33ceab4dd7 100644
|
||||||
|
--- a/login/utmpname.c
|
||||||
|
+++ b/login/utmpname.c
|
||||||
|
@@ -42,8 +42,7 @@ __utmpname (const char *file)
|
||||||
|
__libc_lock_lock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
/* Close the old file. */
|
||||||
|
- (*__libc_utmp_jump_table->endutent) ();
|
||||||
|
- __libc_utmp_jump_table = &__libc_utmp_unknown_functions;
|
||||||
|
+ __libc_endutent ();
|
||||||
|
|
||||||
|
if (strcmp (file, __libc_utmp_file_name) != 0)
|
||||||
|
{
|
||||||
|
diff --git a/manual/users.texi b/manual/users.texi
|
||||||
|
index 4ed79ba26fc8e9d0..a006bb58acfd0568 100644
|
||||||
|
--- a/manual/users.texi
|
||||||
|
+++ b/manual/users.texi
|
||||||
|
@@ -894,9 +894,9 @@ The @code{getlogin} function is declared in @file{unistd.h}, while
|
||||||
|
@c ttyname_r dup @ascuheap @acsmem @acsfd
|
||||||
|
@c strncpy dup ok
|
||||||
|
@c libc_lock_lock dup @asulock @aculock
|
||||||
|
-@c *libc_utmp_jump_table->setutent dup @mtasurace:utent @acsfd
|
||||||
|
-@c *libc_utmp_jump_table->getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer
|
||||||
|
-@c *libc_utmp_jump_table->endutent dup @mtasurace:utent @asulock @aculock
|
||||||
|
+@c __libc_setutent dup @mtasurace:utent @acsfd
|
||||||
|
+@c __libc_getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer
|
||||||
|
+@c __libc_endutent dup @mtasurace:utent @asulock @aculock
|
||||||
|
@c libc_lock_unlock dup ok
|
||||||
|
@c strlen dup ok
|
||||||
|
@c memcpy dup ok
|
||||||
|
@@ -1111,7 +1111,7 @@ compatibility only, @file{utmp.h} defines @code{ut_time} as an alias for
|
||||||
|
|
||||||
|
@c setutent @mtasurace:utent @asulock @aculock @acsfd
|
||||||
|
@c libc_lock_lock dup @asulock @aculock
|
||||||
|
-@c *libc_utmp_jump_table->setutent @mtasurace:utent @acsfd
|
||||||
|
+@c __libc_setutent @mtasurace:utent @acsfd
|
||||||
|
@c setutent_unknown @mtasurace:utent @acsfd
|
||||||
|
@c *libc_utmp_file_functions.setutent = setutent_file @mtasurace:utent @acsfd
|
||||||
|
@c open_not_cancel_2 dup @acsfd
|
||||||
|
@@ -1152,7 +1152,7 @@ A null pointer is returned in case no further entry is available.
|
||||||
|
@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
|
||||||
|
@c endutent @mtasurace:utent @asulock @aculock @acsfd
|
||||||
|
@c libc_lock_lock dup @asulock @aculock
|
||||||
|
-@c *libc_utmp_jump_table->endutent @mtasurace:utent @acsfd
|
||||||
|
+@c __libc_endutent @mtasurace:utent @acsfd
|
||||||
|
@c endutent_unknown ok
|
||||||
|
@c endutent_file @mtasurace:utent @acsfd
|
||||||
|
@c close_not_cancel_no_status dup @acsfd
|
||||||
|
@@ -1230,7 +1230,7 @@ over again.
|
||||||
|
@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
|
||||||
|
@c pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd
|
||||||
|
@c libc_lock_lock dup @asulock @aculock
|
||||||
|
-@c *libc_utmp_jump_table->pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
|
||||||
|
+@c __libc_pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
|
||||||
|
@c pututline_unknown @mtasurace:utent @acsfd
|
||||||
|
@c setutent_unknown dup @mtasurace:utent @acsfd
|
||||||
|
@c pututline_file @mtascusig:ALRM @mtascutimer @acsfd
|
||||||
|
@@ -1282,7 +1282,7 @@ user-provided buffer.
|
||||||
|
@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
|
||||||
|
@c getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd
|
||||||
|
@c libc_lock_lock dup @asulock @aculock
|
||||||
|
-@c *libc_utmp_jump_table->getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
|
||||||
|
+@c __libc_getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
|
||||||
|
@c getutent_r_unknown @mtasurace:utent @acsfd
|
||||||
|
@c setutent_unknown dup @mtasurace:utent @acsfd
|
||||||
|
@c getutent_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer
|
||||||
|
@@ -1319,7 +1319,7 @@ This function is a GNU extension.
|
||||||
|
@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
|
||||||
|
@c getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd
|
||||||
|
@c libc_lock_lock dup @asulock @aculock
|
||||||
|
-@c *libc_utmp_jump_table->getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
|
||||||
|
+@c __libc_getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
|
||||||
|
@c getutid_r_unknown @mtasurace:utent @acsfd
|
||||||
|
@c setutent_unknown dup @mtasurace:utent @acsfd
|
||||||
|
@c getutid_r_file @mtascusig:ALRM @mtascutimer
|
||||||
|
@@ -1349,7 +1349,7 @@ This function is a GNU extension.
|
||||||
|
@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
|
||||||
|
@c getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd
|
||||||
|
@c libc_lock_lock dup @asulock @aculock
|
||||||
|
-@c *libc_utmp_jump_table->getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
|
||||||
|
+@c __libc_getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
|
||||||
|
@c getutline_r_unknown @mtasurace:utent @acsfd
|
||||||
|
@c setutent_unknown dup @mtasurace:utent @acsfd
|
||||||
|
@c getutline_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer
|
||||||
|
@@ -1393,7 +1393,7 @@ be used.
|
||||||
|
@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}}
|
||||||
|
@c utmpname @mtasurace:utent @asulock @ascuheap @aculock @acsmem
|
||||||
|
@c libc_lock_lock dup @asulock @aculock
|
||||||
|
-@c *libc_utmp_jump_table->endutent dup @mtasurace:utent
|
||||||
|
+@c __libc_endutent dup @mtasurace:utent
|
||||||
|
@c strcmp dup ok
|
||||||
|
@c free dup @ascuheap @acsmem
|
||||||
|
@c strdup dup @ascuheap @acsmem
|
||||||
|
diff --git a/sysdeps/unix/getlogin_r.c b/sysdeps/unix/getlogin_r.c
|
||||||
|
index 444df7e4d3210cf6..180c0bbca13d0f87 100644
|
||||||
|
--- a/sysdeps/unix/getlogin_r.c
|
||||||
|
+++ b/sysdeps/unix/getlogin_r.c
|
||||||
|
@@ -64,8 +64,8 @@ __getlogin_r (char *name, size_t name_len)
|
||||||
|
held so that our search is thread-safe. */
|
||||||
|
|
||||||
|
__libc_lock_lock (__libc_utmp_lock);
|
||||||
|
- (*__libc_utmp_jump_table->setutent) ();
|
||||||
|
- result = (*__libc_utmp_jump_table->getutline_r) (&line, &buffer, &ut);
|
||||||
|
+ __libc_setutent ();
|
||||||
|
+ result = __libc_getutline_r (&line, &buffer, &ut);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
if (errno == ESRCH)
|
||||||
|
@@ -74,8 +74,7 @@ __getlogin_r (char *name, size_t name_len)
|
||||||
|
else
|
||||||
|
result = errno;
|
||||||
|
}
|
||||||
|
- (*__libc_utmp_jump_table->endutent) ();
|
||||||
|
- __libc_utmp_jump_table = &__libc_utmp_unknown_functions;
|
||||||
|
+ __libc_endutent ();
|
||||||
|
__libc_lock_unlock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
if (result == 0)
|
389
SOURCES/glibc-rh1749439-10.patch
Normal file
389
SOURCES/glibc-rh1749439-10.patch
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
commit be6b16d975683e6cca57852cd4cfe715b2a9d8b1
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Nov 7 18:15:18 2019 +0100
|
||||||
|
|
||||||
|
login: Acquire write lock early in pututline [BZ #24882]
|
||||||
|
|
||||||
|
It has been reported that due to lack of fairness in POSIX file
|
||||||
|
locking, the current reader-to-writer lock upgrade can result in
|
||||||
|
lack of forward progress. Acquiring the write lock directly
|
||||||
|
hopefully avoids this issue if there are only writers.
|
||||||
|
|
||||||
|
This also fixes bug 24882 due to the cache revalidation in
|
||||||
|
__libc_pututline.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Change-Id: I57e31ae30719e609a53505a0924dda101d46372e
|
||||||
|
|
||||||
|
diff --git a/login/Makefile b/login/Makefile
|
||||||
|
index 82132c83fd799357..030cf489b2e037d4 100644
|
||||||
|
--- a/login/Makefile
|
||||||
|
+++ b/login/Makefile
|
||||||
|
@@ -44,7 +44,7 @@ subdir-dirs = programs
|
||||||
|
vpath %.c programs
|
||||||
|
|
||||||
|
tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
|
||||||
|
- tst-pututxline-lockfail
|
||||||
|
+ tst-pututxline-lockfail tst-pututxline-cache
|
||||||
|
|
||||||
|
# Build the -lutil library with these extra functions.
|
||||||
|
extra-libs := libutil
|
||||||
|
@@ -74,3 +74,4 @@ $(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force)
|
||||||
|
-$(INSTALL_PROGRAM) -m 4755 -o root $< $@
|
||||||
|
|
||||||
|
$(objpfx)tst-pututxline-lockfail: $(shared-thread-library)
|
||||||
|
+$(objpfx)tst-pututxline-cache: $(shared-thread-library)
|
||||||
|
diff --git a/login/tst-pututxline-cache.c b/login/tst-pututxline-cache.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..3f30dd1776711769
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/login/tst-pututxline-cache.c
|
||||||
|
@@ -0,0 +1,193 @@
|
||||||
|
+/* Test case for cache invalidation after concurrent write (bug 24882).
|
||||||
|
+ Copyright (C) 2019 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; see the file COPYING.LIB. If
|
||||||
|
+ not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* This test writes an entry to the utmpx file, reads it (so that it
|
||||||
|
+ is cached) in process1, and overwrites the same entry in process2
|
||||||
|
+ with something that does not match the search criteria. At this
|
||||||
|
+ point, the cache of the first process is stale, and when process1
|
||||||
|
+ attempts to write a new record which would have gone to the same
|
||||||
|
+ place (as indicated by the cache), it needs to realize that it has
|
||||||
|
+ to pick a different slot because the old slot is now used for
|
||||||
|
+ something else. */
|
||||||
|
+
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/namespace.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/temp_file.h>
|
||||||
|
+#include <support/xthread.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+#include <utmp.h>
|
||||||
|
+#include <utmpx.h>
|
||||||
|
+
|
||||||
|
+/* Set to the path of the utmp file. */
|
||||||
|
+static char *utmp_file;
|
||||||
|
+
|
||||||
|
+/* Used to synchronize the subprocesses. The barrier itself is
|
||||||
|
+ allocated in shared memory. */
|
||||||
|
+static pthread_barrier_t *barrier;
|
||||||
|
+
|
||||||
|
+/* setutxent with error checking. */
|
||||||
|
+static void
|
||||||
|
+xsetutxent (void)
|
||||||
|
+{
|
||||||
|
+ errno = 0;
|
||||||
|
+ setutxent ();
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* getutxent with error checking. */
|
||||||
|
+static struct utmpx *
|
||||||
|
+xgetutxent (void)
|
||||||
|
+{
|
||||||
|
+ errno = 0;
|
||||||
|
+ struct utmpx *result = getutxent ();
|
||||||
|
+ if (result == NULL)
|
||||||
|
+ FAIL_EXIT1 ("getutxent: %m");
|
||||||
|
+ return result;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+put_entry (const char *id, pid_t pid, const char *user, const char *line)
|
||||||
|
+{
|
||||||
|
+ struct utmpx ut =
|
||||||
|
+ {
|
||||||
|
+ .ut_type = LOGIN_PROCESS,
|
||||||
|
+ .ut_pid = pid,
|
||||||
|
+ .ut_host = "localhost",
|
||||||
|
+ };
|
||||||
|
+ strcpy (ut.ut_id, id);
|
||||||
|
+ strncpy (ut.ut_user, user, sizeof (ut.ut_user));
|
||||||
|
+ strncpy (ut.ut_line, line, sizeof (ut.ut_line));
|
||||||
|
+ TEST_VERIFY (pututxline (&ut) != NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Use two cooperating subprocesses to avoid issues related to
|
||||||
|
+ unlock-on-close semantics of POSIX advisory locks. */
|
||||||
|
+
|
||||||
|
+static __attribute__ ((noreturn)) void
|
||||||
|
+process1 (void)
|
||||||
|
+{
|
||||||
|
+ TEST_COMPARE (utmpname (utmp_file), 0);
|
||||||
|
+
|
||||||
|
+ /* Create an entry. */
|
||||||
|
+ xsetutxent ();
|
||||||
|
+ put_entry ("1", 101, "root", "process1");
|
||||||
|
+
|
||||||
|
+ /* Retrieve the entry. This will fill the internal cache. */
|
||||||
|
+ {
|
||||||
|
+ errno = 0;
|
||||||
|
+ setutxent ();
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+ struct utmpx ut =
|
||||||
|
+ {
|
||||||
|
+ .ut_type = LOGIN_PROCESS,
|
||||||
|
+ .ut_line = "process1",
|
||||||
|
+ };
|
||||||
|
+ struct utmpx *result = getutxline (&ut);
|
||||||
|
+ if (result == NULL)
|
||||||
|
+ FAIL_EXIT1 ("getutxline (\"process1\"): %m");
|
||||||
|
+ TEST_COMPARE (result->ut_pid, 101);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Signal the other process to overwrite the entry. */
|
||||||
|
+ xpthread_barrier_wait (barrier);
|
||||||
|
+
|
||||||
|
+ /* Wait for the other process to complete the write operation. */
|
||||||
|
+ xpthread_barrier_wait (barrier);
|
||||||
|
+
|
||||||
|
+ /* Add another entry. Note: This time, there is no setutxent call. */
|
||||||
|
+ put_entry ("1", 103, "root", "process1");
|
||||||
|
+
|
||||||
|
+ _exit (0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+process2 (void *closure)
|
||||||
|
+{
|
||||||
|
+ /* Wait for the first process to write its entry. */
|
||||||
|
+ xpthread_barrier_wait (barrier);
|
||||||
|
+
|
||||||
|
+ /* Truncate the file. The glibc interface does not support
|
||||||
|
+ re-purposing records, but an external expiration mechanism may
|
||||||
|
+ trigger this. */
|
||||||
|
+ TEST_COMPARE (truncate64 (utmp_file, 0), 0);
|
||||||
|
+
|
||||||
|
+ /* Write the replacement entry. */
|
||||||
|
+ TEST_COMPARE (utmpname (utmp_file), 0);
|
||||||
|
+ xsetutxent ();
|
||||||
|
+ put_entry ("2", 102, "user", "process2");
|
||||||
|
+
|
||||||
|
+ /* Signal the other process that the entry has been replaced. */
|
||||||
|
+ xpthread_barrier_wait (barrier);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ xclose (create_temp_file ("tst-tumpx-cache-write-", &utmp_file));
|
||||||
|
+ {
|
||||||
|
+ pthread_barrierattr_t attr;
|
||||||
|
+ xpthread_barrierattr_init (&attr);
|
||||||
|
+ xpthread_barrierattr_setpshared (&attr, PTHREAD_SCOPE_PROCESS);
|
||||||
|
+ barrier = support_shared_allocate (sizeof (*barrier));
|
||||||
|
+ xpthread_barrier_init (barrier, &attr, 2);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Run both subprocesses in parallel. */
|
||||||
|
+ {
|
||||||
|
+ pid_t pid1 = xfork ();
|
||||||
|
+ if (pid1 == 0)
|
||||||
|
+ process1 ();
|
||||||
|
+ support_isolate_in_subprocess (process2, NULL);
|
||||||
|
+ int status;
|
||||||
|
+ xwaitpid (pid1, &status, 0);
|
||||||
|
+ TEST_COMPARE (status, 0);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Check that the utmpx database contains the expected records. */
|
||||||
|
+ {
|
||||||
|
+ TEST_COMPARE (utmpname (utmp_file), 0);
|
||||||
|
+ xsetutxent ();
|
||||||
|
+
|
||||||
|
+ struct utmpx *ut = xgetutxent ();
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_id, "2");
|
||||||
|
+ TEST_COMPARE (ut->ut_pid, 102);
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_user, "user");
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_line, "process2");
|
||||||
|
+
|
||||||
|
+ ut = xgetutxent ();
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_id, "1");
|
||||||
|
+ TEST_COMPARE (ut->ut_pid, 103);
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_user, "root");
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_line, "process1");
|
||||||
|
+
|
||||||
|
+ if (getutxent () != NULL)
|
||||||
|
+ FAIL_EXIT1 ("additional utmpx entry");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ xpthread_barrier_destroy (barrier);
|
||||||
|
+ support_shared_free (barrier);
|
||||||
|
+ free (utmp_file);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index 9ad80364682bae92..6bba120db9cc574e 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -186,19 +186,11 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
|
||||||
|
|
||||||
|
/* Search for *ID, updating last_entry and file_offset. Return 0 on
|
||||||
|
- success and -1 on failure. If the locking operation failed, write
|
||||||
|
- true to *LOCK_FAILED. */
|
||||||
|
+ success and -1 on failure. Does not perform locking; for that see
|
||||||
|
+ internal_getut_r below. */
|
||||||
|
static int
|
||||||
|
-internal_getut_r (const struct utmp *id, bool *lock_failed)
|
||||||
|
+internal_getut_nolock (const struct utmp *id)
|
||||||
|
{
|
||||||
|
- int result = -1;
|
||||||
|
-
|
||||||
|
- if (try_file_lock (file_fd, F_RDLCK))
|
||||||
|
- {
|
||||||
|
- *lock_failed = true;
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
|
||||||
|
|| id->ut_type == OLD_TIME || id->ut_type == NEW_TIME)
|
||||||
|
{
|
||||||
|
@@ -213,7 +205,7 @@ internal_getut_r (const struct utmp *id, bool *lock_failed)
|
||||||
|
{
|
||||||
|
__set_errno (ESRCH);
|
||||||
|
file_offset = -1l;
|
||||||
|
- goto unlock_return;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
file_offset += sizeof (struct utmp);
|
||||||
|
|
||||||
|
@@ -234,7 +226,7 @@ internal_getut_r (const struct utmp *id, bool *lock_failed)
|
||||||
|
{
|
||||||
|
__set_errno (ESRCH);
|
||||||
|
file_offset = -1l;
|
||||||
|
- goto unlock_return;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
file_offset += sizeof (struct utmp);
|
||||||
|
|
||||||
|
@@ -243,15 +235,26 @@ internal_getut_r (const struct utmp *id, bool *lock_failed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- result = 0;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
|
||||||
|
-unlock_return:
|
||||||
|
- file_unlock (file_fd);
|
||||||
|
+/* Search for *ID, updating last_entry and file_offset. Return 0 on
|
||||||
|
+ success and -1 on failure. If the locking operation failed, write
|
||||||
|
+ true to *LOCK_FAILED. */
|
||||||
|
+static int
|
||||||
|
+internal_getut_r (const struct utmp *id, bool *lock_failed)
|
||||||
|
+{
|
||||||
|
+ if (try_file_lock (file_fd, F_RDLCK))
|
||||||
|
+ {
|
||||||
|
+ *lock_failed = true;
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
+ int result = internal_getut_nolock (id);
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
/* For implementing this function we don't use the getutent_r function
|
||||||
|
because we can avoid the reposition on every new entry this way. */
|
||||||
|
int
|
||||||
|
@@ -279,7 +282,6 @@ __libc_getutid_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
/* For implementing this function we don't use the getutent_r function
|
||||||
|
because we can avoid the reposition on every new entry this way. */
|
||||||
|
int
|
||||||
|
@@ -336,7 +338,6 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct utmp *pbuf;
|
||||||
|
- int found;
|
||||||
|
|
||||||
|
if (! file_writable)
|
||||||
|
{
|
||||||
|
@@ -358,7 +359,12 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
file_writable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Exclude other writers before validating the cache. */
|
||||||
|
+ if (try_file_lock (file_fd, F_WRLCK))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
/* Find the correct place to insert the data. */
|
||||||
|
+ bool found = false;
|
||||||
|
if (file_offset > 0
|
||||||
|
&& ((last_entry.ut_type == data->ut_type
|
||||||
|
&& (last_entry.ut_type == RUN_LVL
|
||||||
|
@@ -366,23 +372,30 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
|| last_entry.ut_type == OLD_TIME
|
||||||
|
|| last_entry.ut_type == NEW_TIME))
|
||||||
|
|| __utmp_equal (&last_entry, data)))
|
||||||
|
- found = 1;
|
||||||
|
- else
|
||||||
|
{
|
||||||
|
- bool lock_failed = false;
|
||||||
|
- found = internal_getut_r (data, &lock_failed);
|
||||||
|
-
|
||||||
|
- if (__builtin_expect (lock_failed, false))
|
||||||
|
+ if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0)
|
||||||
|
{
|
||||||
|
- __set_errno (EAGAIN);
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
+ if (__read_nocancel (file_fd, &last_entry, sizeof (last_entry))
|
||||||
|
+ != sizeof (last_entry))
|
||||||
|
+ {
|
||||||
|
+ if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0)
|
||||||
|
+ {
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ found = false;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ found = __utmp_equal (&last_entry, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (try_file_lock (file_fd, F_WRLCK))
|
||||||
|
- return NULL;
|
||||||
|
+ if (!found)
|
||||||
|
+ found = internal_getut_nolock (data) >= 0;
|
||||||
|
|
||||||
|
- if (found < 0)
|
||||||
|
+ if (!found)
|
||||||
|
{
|
||||||
|
/* We append the next entry. */
|
||||||
|
file_offset = __lseek64 (file_fd, 0, SEEK_END);
|
||||||
|
@@ -411,7 +424,7 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
{
|
||||||
|
/* If we appended a new record this is only partially written.
|
||||||
|
Remove it. */
|
||||||
|
- if (found < 0)
|
||||||
|
+ if (!found)
|
||||||
|
(void) __ftruncate64 (file_fd, file_offset);
|
||||||
|
pbuf = NULL;
|
||||||
|
}
|
138
SOURCES/glibc-rh1749439-11.patch
Normal file
138
SOURCES/glibc-rh1749439-11.patch
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
commit 76a7c103eb9060f9e3ba01d073ae4621a17d8b46
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Tue Nov 12 12:02:57 2019 +0100
|
||||||
|
|
||||||
|
login: Introduce matches_last_entry to utmp processing
|
||||||
|
|
||||||
|
This simplifies internal_getut_nolock and fixes a regression,
|
||||||
|
introduced in commit be6b16d975683e6cca57852cd4cfe715b2a9d8b1
|
||||||
|
("login: Acquire write lock early in pututline [BZ #24882]")
|
||||||
|
in pututxline because __utmp_equal can only compare process-related
|
||||||
|
utmp entries.
|
||||||
|
|
||||||
|
Fixes: be6b16d975683e6cca57852cd4cfe715b2a9d8b1
|
||||||
|
Change-Id: Ib8a85002f7f87ee41590846d16d7e52bdb82f5a5
|
||||||
|
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index 6bba120db9cc574e..e653d14967c4fb7a 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -43,6 +43,25 @@ static off64_t file_offset;
|
||||||
|
/* Cache for the last read entry. */
|
||||||
|
static struct utmp last_entry;
|
||||||
|
|
||||||
|
+/* Returns true if *ENTRY matches last_entry, based on
|
||||||
|
+ data->ut_type. */
|
||||||
|
+static bool
|
||||||
|
+matches_last_entry (const struct utmp *data)
|
||||||
|
+{
|
||||||
|
+ if (file_offset <= 0)
|
||||||
|
+ /* Nothing has been read. last_entry is stale and cannot match. */
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ if (data->ut_type == RUN_LVL
|
||||||
|
+ || data->ut_type == BOOT_TIME
|
||||||
|
+ || data->ut_type == OLD_TIME
|
||||||
|
+ || data->ut_type == NEW_TIME)
|
||||||
|
+ /* For some entry types, only a type match is required. */
|
||||||
|
+ return data->ut_type == last_entry.ut_type;
|
||||||
|
+ else
|
||||||
|
+ /* For the process-related entries, a full match is needed. */
|
||||||
|
+ return __utmp_equal (&last_entry, data);
|
||||||
|
+}
|
||||||
|
|
||||||
|
/* Locking timeout. */
|
||||||
|
#ifndef TIMEOUT
|
||||||
|
@@ -133,9 +152,6 @@ __libc_setutent (void)
|
||||||
|
__lseek64 (file_fd, 0, SEEK_SET);
|
||||||
|
file_offset = 0;
|
||||||
|
|
||||||
|
- /* Make sure the entry won't match. */
|
||||||
|
- last_entry.ut_type = -1;
|
||||||
|
-
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -191,48 +207,20 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
static int
|
||||||
|
internal_getut_nolock (const struct utmp *id)
|
||||||
|
{
|
||||||
|
- if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
|
||||||
|
- || id->ut_type == OLD_TIME || id->ut_type == NEW_TIME)
|
||||||
|
+ while (1)
|
||||||
|
{
|
||||||
|
- /* Search for next entry with type RUN_LVL, BOOT_TIME,
|
||||||
|
- OLD_TIME, or NEW_TIME. */
|
||||||
|
-
|
||||||
|
- while (1)
|
||||||
|
+ /* Read the next entry. */
|
||||||
|
+ if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp))
|
||||||
|
+ != sizeof (struct utmp))
|
||||||
|
{
|
||||||
|
- /* Read the next entry. */
|
||||||
|
- if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp))
|
||||||
|
- != sizeof (struct utmp))
|
||||||
|
- {
|
||||||
|
- __set_errno (ESRCH);
|
||||||
|
- file_offset = -1l;
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
- file_offset += sizeof (struct utmp);
|
||||||
|
-
|
||||||
|
- if (id->ut_type == last_entry.ut_type)
|
||||||
|
- break;
|
||||||
|
+ __set_errno (ESRCH);
|
||||||
|
+ file_offset = -1l;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- /* Search for the next entry with the specified ID and with type
|
||||||
|
- INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS. */
|
||||||
|
-
|
||||||
|
- while (1)
|
||||||
|
- {
|
||||||
|
- /* Read the next entry. */
|
||||||
|
- if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp))
|
||||||
|
- != sizeof (struct utmp))
|
||||||
|
- {
|
||||||
|
- __set_errno (ESRCH);
|
||||||
|
- file_offset = -1l;
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
- file_offset += sizeof (struct utmp);
|
||||||
|
+ file_offset += sizeof (struct utmp);
|
||||||
|
|
||||||
|
- if (__utmp_equal (&last_entry, id))
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
+ if (matches_last_entry (id))
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -365,13 +353,7 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
|
||||||
|
/* Find the correct place to insert the data. */
|
||||||
|
bool found = false;
|
||||||
|
- if (file_offset > 0
|
||||||
|
- && ((last_entry.ut_type == data->ut_type
|
||||||
|
- && (last_entry.ut_type == RUN_LVL
|
||||||
|
- || last_entry.ut_type == BOOT_TIME
|
||||||
|
- || last_entry.ut_type == OLD_TIME
|
||||||
|
- || last_entry.ut_type == NEW_TIME))
|
||||||
|
- || __utmp_equal (&last_entry, data)))
|
||||||
|
+ if (matches_last_entry (data))
|
||||||
|
{
|
||||||
|
if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0)
|
||||||
|
{
|
||||||
|
@@ -389,7 +371,7 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
- found = __utmp_equal (&last_entry, data);
|
||||||
|
+ found = matches_last_entry (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
114
SOURCES/glibc-rh1749439-12.patch
Normal file
114
SOURCES/glibc-rh1749439-12.patch
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
commit fed33b0fb03d1942a6713286176d42869c0f1580
|
||||||
|
Author: Leandro Pereira <leandro.pereira@microsoft.com>
|
||||||
|
Date: Wed Oct 2 12:42:28 2019 -0400
|
||||||
|
|
||||||
|
Add nocancel version of pread64()
|
||||||
|
|
||||||
|
This is in preparation for changes in the dynamic linker so that
|
||||||
|
pread() is used instead of lseek()+read().
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
sysdeps/unix/sysv/linux/Makefile
|
||||||
|
(Textual conflict in routines list.)
|
||||||
|
|
||||||
|
diff --git a/sysdeps/generic/not-cancel.h b/sysdeps/generic/not-cancel.h
|
||||||
|
index d9f8a75dbda85ed5..260e6e4081f5fe16 100644
|
||||||
|
--- a/sysdeps/generic/not-cancel.h
|
||||||
|
+++ b/sysdeps/generic/not-cancel.h
|
||||||
|
@@ -41,6 +41,8 @@
|
||||||
|
(void) __close (fd)
|
||||||
|
#define __read_nocancel(fd, buf, n) \
|
||||||
|
__read (fd, buf, n)
|
||||||
|
+#define __pread64_nocancel(fd, buf, count, offset) \
|
||||||
|
+ __pread64 (fd, buf, count, offset)
|
||||||
|
#define __write_nocancel(fd, buf, n) \
|
||||||
|
__write (fd, buf, n)
|
||||||
|
#define __writev_nocancel_nostatus(fd, iov, n) \
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
|
||||||
|
index 773aaea0e980bdd6..fb4ccd63ddec7eca 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/Makefile
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/Makefile
|
||||||
|
@@ -174,7 +174,8 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \
|
||||||
|
close_nocancel fcntl_nocancel nanosleep_nocancel \
|
||||||
|
open_nocancel open64_nocancel \
|
||||||
|
openat_nocancel openat64_nocancel \
|
||||||
|
- pause_nocancel read_nocancel waitpid_nocancel write_nocancel
|
||||||
|
+ pause_nocancel read_nocancel pread64_nocancel \
|
||||||
|
+ waitpid_nocancel write_nocancel
|
||||||
|
|
||||||
|
sysdep_headers += bits/fcntl-linux.h
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
|
||||||
|
index 336c13b57dba727a..95759bead1b0b3ca 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/Versions
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/Versions
|
||||||
|
@@ -176,6 +176,7 @@ libc {
|
||||||
|
__syscall_rt_sigqueueinfo;
|
||||||
|
__open_nocancel;
|
||||||
|
__read_nocancel;
|
||||||
|
+ __pread64_nocancel;
|
||||||
|
__close_nocancel;
|
||||||
|
__sigtimedwait;
|
||||||
|
# functions used by nscd
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h
|
||||||
|
index 09de92dee9437d98..e58db475682a8c6a 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/not-cancel.h
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/not-cancel.h
|
||||||
|
@@ -43,6 +43,9 @@ __typeof (openat64) __openat64_nocancel;
|
||||||
|
/* Non cancellable read syscall. */
|
||||||
|
__typeof (__read) __read_nocancel;
|
||||||
|
|
||||||
|
+/* Non cancellable pread syscall (LFS version). */
|
||||||
|
+__typeof (__pread64) __pread64_nocancel;
|
||||||
|
+
|
||||||
|
/* Uncancelable write. */
|
||||||
|
__typeof (__write) __write_nocancel;
|
||||||
|
|
||||||
|
@@ -84,6 +87,7 @@ hidden_proto (__open64_nocancel)
|
||||||
|
hidden_proto (__openat_nocancel)
|
||||||
|
hidden_proto (__openat64_nocancel)
|
||||||
|
hidden_proto (__read_nocancel)
|
||||||
|
+hidden_proto (__pread64_nocancel)
|
||||||
|
hidden_proto (__write_nocancel)
|
||||||
|
hidden_proto (__close_nocancel)
|
||||||
|
hidden_proto (__waitpid_nocancel)
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/pread64_nocancel.c b/sysdeps/unix/sysv/linux/pread64_nocancel.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..dab61260e5db43b5
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/pread64_nocancel.c
|
||||||
|
@@ -0,0 +1,32 @@
|
||||||
|
+/* Linux pread64() syscall implementation -- non-cancellable.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <sysdep-cancel.h>
|
||||||
|
+#include <not-cancel.h>
|
||||||
|
+
|
||||||
|
+#ifndef __NR_pread64
|
||||||
|
+# define __NR_pread64 __NR_pread
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ssize_t
|
||||||
|
+__pread64_nocancel (int fd, void *buf, size_t count, off64_t offset)
|
||||||
|
+{
|
||||||
|
+ return INLINE_SYSCALL_CALL (pread64, fd, buf, count, SYSCALL_LL64_PRW (offset));
|
||||||
|
+}
|
||||||
|
+hidden_def (__pread64_nocancel)
|
307
SOURCES/glibc-rh1749439-13.patch
Normal file
307
SOURCES/glibc-rh1749439-13.patch
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
commit d4625a19fe64f664119a541b317fb83de01bb273
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Tue Nov 12 12:25:49 2019 +0100
|
||||||
|
|
||||||
|
login: Use pread64 in utmp implementation
|
||||||
|
|
||||||
|
This reduces the possible error scenarios considerably because
|
||||||
|
no longer can file seek fail, leaving the file descriptor in an
|
||||||
|
inconsistent state and out of sync with the cache.
|
||||||
|
|
||||||
|
As a result, it is possible to avoid setting file_offset to -1
|
||||||
|
to make an error persistent. Instead, subsequent calls will retry
|
||||||
|
the operation and report any errors returned by the kernel.
|
||||||
|
|
||||||
|
This change also avoids reading the file from the start if pututline
|
||||||
|
is called multiple times, to work around lock acquisition failures
|
||||||
|
due to timeouts.
|
||||||
|
|
||||||
|
Change-Id: If21ea0c162c38830a89331ea93cddec14c0974de
|
||||||
|
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index e653d14967c4fb7a..c828a28ac54c150e 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -162,12 +162,35 @@ maybe_setutent (void)
|
||||||
|
return file_fd >= 0 || __libc_setutent ();
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Reads the entry at file_offset, storing it in last_entry and
|
||||||
|
+ updating file_offset on success. Returns -1 for a read error, 0
|
||||||
|
+ for EOF, and 1 for a successful read. last_entry and file_offset
|
||||||
|
+ are only updated on a successful and complete read. */
|
||||||
|
+static ssize_t
|
||||||
|
+read_last_entry (void)
|
||||||
|
+{
|
||||||
|
+ struct utmp buffer;
|
||||||
|
+ ssize_t nbytes = __pread64_nocancel (file_fd, &buffer, sizeof (buffer),
|
||||||
|
+ file_offset);
|
||||||
|
+ if (nbytes < 0)
|
||||||
|
+ return -1;
|
||||||
|
+ else if (nbytes != sizeof (buffer))
|
||||||
|
+ /* Assume EOF. */
|
||||||
|
+ return 0;
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ last_entry = buffer;
|
||||||
|
+ file_offset += sizeof (buffer);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
__libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
{
|
||||||
|
- ssize_t nbytes;
|
||||||
|
+ int saved_errno = errno;
|
||||||
|
|
||||||
|
- if (!maybe_setutent () || file_offset == -1l)
|
||||||
|
+ if (!maybe_setutent ())
|
||||||
|
{
|
||||||
|
/* Not available. */
|
||||||
|
*result = NULL;
|
||||||
|
@@ -175,25 +198,22 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (try_file_lock (file_fd, F_RDLCK))
|
||||||
|
- nbytes = 0;
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- /* Read the next entry. */
|
||||||
|
- nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp));
|
||||||
|
- file_unlock (file_fd);
|
||||||
|
- }
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
- if (nbytes != sizeof (struct utmp))
|
||||||
|
+ ssize_t nbytes = read_last_entry ();
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
+
|
||||||
|
+ if (nbytes <= 0) /* Read error or EOF. */
|
||||||
|
{
|
||||||
|
- if (nbytes != 0)
|
||||||
|
- file_offset = -1l;
|
||||||
|
+ if (nbytes == 0)
|
||||||
|
+ /* errno should be unchanged to indicate success. A premature
|
||||||
|
+ EOF is treated like an EOF (missing complete record at the
|
||||||
|
+ end). */
|
||||||
|
+ __set_errno (saved_errno);
|
||||||
|
*result = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Update position pointer. */
|
||||||
|
- file_offset += sizeof (struct utmp);
|
||||||
|
-
|
||||||
|
memcpy (buffer, &last_entry, sizeof (struct utmp));
|
||||||
|
*result = buffer;
|
||||||
|
|
||||||
|
@@ -209,15 +229,15 @@ internal_getut_nolock (const struct utmp *id)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
- /* Read the next entry. */
|
||||||
|
- if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp))
|
||||||
|
- != sizeof (struct utmp))
|
||||||
|
+ ssize_t nbytes = read_last_entry ();
|
||||||
|
+ if (nbytes < 0)
|
||||||
|
+ return -1;
|
||||||
|
+ if (nbytes == 0)
|
||||||
|
{
|
||||||
|
+ /* End of file reached. */
|
||||||
|
__set_errno (ESRCH);
|
||||||
|
- file_offset = -1l;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
- file_offset += sizeof (struct utmp);
|
||||||
|
|
||||||
|
if (matches_last_entry (id))
|
||||||
|
break;
|
||||||
|
@@ -249,7 +269,7 @@ int
|
||||||
|
__libc_getutid_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
struct utmp **result)
|
||||||
|
{
|
||||||
|
- if (!maybe_setutent () || file_offset == -1l)
|
||||||
|
+ if (!maybe_setutent ())
|
||||||
|
{
|
||||||
|
*result = NULL;
|
||||||
|
return -1;
|
||||||
|
@@ -276,7 +296,7 @@ int
|
||||||
|
__libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
struct utmp **result)
|
||||||
|
{
|
||||||
|
- if (!maybe_setutent () || file_offset == -1l)
|
||||||
|
+ if (!maybe_setutent ())
|
||||||
|
{
|
||||||
|
*result = NULL;
|
||||||
|
return -1;
|
||||||
|
@@ -290,16 +310,21 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
- /* Read the next entry. */
|
||||||
|
- if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp))
|
||||||
|
- != sizeof (struct utmp))
|
||||||
|
+ ssize_t nbytes = read_last_entry ();
|
||||||
|
+ if (nbytes < 0)
|
||||||
|
{
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
+ *result = NULL;
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ if (nbytes == 0)
|
||||||
|
+ {
|
||||||
|
+ /* End of file reached. */
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
__set_errno (ESRCH);
|
||||||
|
- file_offset = -1l;
|
||||||
|
*result = NULL;
|
||||||
|
- goto unlock_return;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
- file_offset += sizeof (struct utmp);
|
||||||
|
|
||||||
|
/* Stop if we found a user or login entry. */
|
||||||
|
if ((last_entry.ut_type == USER_PROCESS
|
||||||
|
@@ -309,20 +334,18 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
memcpy (buffer, &last_entry, sizeof (struct utmp));
|
||||||
|
*result = buffer;
|
||||||
|
|
||||||
|
-unlock_return:
|
||||||
|
- file_unlock (file_fd);
|
||||||
|
-
|
||||||
|
- return ((*result == NULL) ? -1 : 0);
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct utmp *
|
||||||
|
__libc_pututline (const struct utmp *data)
|
||||||
|
{
|
||||||
|
- if (!maybe_setutent () || file_offset == -1l)
|
||||||
|
+ if (!maybe_setutent ())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct utmp *pbuf;
|
||||||
|
@@ -337,8 +360,7 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
if (new_fd == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
- if (__lseek64 (new_fd, __lseek64 (file_fd, 0, SEEK_CUR), SEEK_SET) == -1
|
||||||
|
- || __dup2 (new_fd, file_fd) < 0)
|
||||||
|
+ if (__dup2 (new_fd, file_fd) < 0)
|
||||||
|
{
|
||||||
|
__close_nocancel_nostatus (new_fd);
|
||||||
|
return NULL;
|
||||||
|
@@ -355,69 +377,70 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
bool found = false;
|
||||||
|
if (matches_last_entry (data))
|
||||||
|
{
|
||||||
|
- if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0)
|
||||||
|
+ /* Read back the entry under the write lock. */
|
||||||
|
+ file_offset -= sizeof (last_entry);
|
||||||
|
+ ssize_t nbytes = read_last_entry ();
|
||||||
|
+ if (nbytes < 0)
|
||||||
|
{
|
||||||
|
file_unlock (file_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
- if (__read_nocancel (file_fd, &last_entry, sizeof (last_entry))
|
||||||
|
- != sizeof (last_entry))
|
||||||
|
- {
|
||||||
|
- if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0)
|
||||||
|
- {
|
||||||
|
- file_unlock (file_fd);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
- found = false;
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
+ if (nbytes == 0)
|
||||||
|
+ /* End of file reached. */
|
||||||
|
+ found = false;
|
||||||
|
else
|
||||||
|
found = matches_last_entry (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
+ /* Search forward for the entry. */
|
||||||
|
found = internal_getut_nolock (data) >= 0;
|
||||||
|
|
||||||
|
+ off64_t write_offset;
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
/* We append the next entry. */
|
||||||
|
- file_offset = __lseek64 (file_fd, 0, SEEK_END);
|
||||||
|
- if (file_offset % sizeof (struct utmp) != 0)
|
||||||
|
- {
|
||||||
|
- file_offset -= file_offset % sizeof (struct utmp);
|
||||||
|
- __ftruncate64 (file_fd, file_offset);
|
||||||
|
-
|
||||||
|
- if (__lseek64 (file_fd, 0, SEEK_END) < 0)
|
||||||
|
- {
|
||||||
|
- pbuf = NULL;
|
||||||
|
- goto unlock_return;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ write_offset = __lseek64 (file_fd, 0, SEEK_END);
|
||||||
|
+
|
||||||
|
+ /* Round down to the next multiple of the entry size. This
|
||||||
|
+ ensures any partially-written record is overwritten by the
|
||||||
|
+ new record. */
|
||||||
|
+ write_offset = (write_offset / sizeof (struct utmp)
|
||||||
|
+ * sizeof (struct utmp));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
+ /* Overwrite last_entry. */
|
||||||
|
+ write_offset = file_offset - sizeof (struct utmp);
|
||||||
|
+
|
||||||
|
+ /* Write the new data. */
|
||||||
|
+ ssize_t nbytes;
|
||||||
|
+ if (__lseek64 (file_fd, write_offset, SEEK_SET) < 0
|
||||||
|
+ || (nbytes = __write_nocancel (file_fd, data, sizeof (struct utmp))) < 0)
|
||||||
|
{
|
||||||
|
- /* We replace the just read entry. */
|
||||||
|
- file_offset -= sizeof (struct utmp);
|
||||||
|
- __lseek64 (file_fd, file_offset, SEEK_SET);
|
||||||
|
+ /* There is no need to recover the file position because all
|
||||||
|
+ reads use pread64, and any future write is preceded by
|
||||||
|
+ another seek. */
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Write the new data. */
|
||||||
|
- if (__write_nocancel (file_fd, data, sizeof (struct utmp))
|
||||||
|
- != sizeof (struct utmp))
|
||||||
|
+ if (nbytes != sizeof (struct utmp))
|
||||||
|
{
|
||||||
|
/* If we appended a new record this is only partially written.
|
||||||
|
Remove it. */
|
||||||
|
if (!found)
|
||||||
|
- (void) __ftruncate64 (file_fd, file_offset);
|
||||||
|
- pbuf = NULL;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- file_offset += sizeof (struct utmp);
|
||||||
|
- pbuf = (struct utmp *) data;
|
||||||
|
+ (void) __ftruncate64 (file_fd, write_offset);
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
+ /* Assume that the write failure was due to missing disk
|
||||||
|
+ space. */
|
||||||
|
+ __set_errno (ENOSPC);
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- unlock_return:
|
||||||
|
file_unlock (file_fd);
|
||||||
|
+ file_offset = write_offset + sizeof (struct utmp);
|
||||||
|
+ pbuf = (struct utmp *) data;
|
||||||
|
|
||||||
|
return pbuf;
|
||||||
|
}
|
676
SOURCES/glibc-rh1749439-2.patch
Normal file
676
SOURCES/glibc-rh1749439-2.patch
Normal file
@ -0,0 +1,676 @@
|
|||||||
|
commit a33b817f13170b5c24263b92e7e09880fe797d7e
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Tue Aug 13 12:09:32 2019 +0200
|
||||||
|
|
||||||
|
login: Assume that _HAVE_UT_* constants are true
|
||||||
|
|
||||||
|
Make the GNU version of bits/utmp.h the generic version because
|
||||||
|
all remaining ports use it (with a sysdeps override for
|
||||||
|
Linux s390/s390x).
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
bits/utmp.h
|
||||||
|
sysdeps/gnu/bits/utmp.h
|
||||||
|
(Upstream copyright year change.)
|
||||||
|
|
||||||
|
diff --git a/bits/utmp.h b/bits/utmp.h
|
||||||
|
index 6e8695fbf072e5f1..3c02dd4f3fe4e99b 100644
|
||||||
|
--- a/bits/utmp.h
|
||||||
|
+++ b/bits/utmp.h
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
-/* The `struct utmp' type, describing entries in the utmp file. Generic/BSDish
|
||||||
|
- Copyright (C) 1993-2018 Free Software Foundation, Inc.
|
||||||
|
+/* The `struct utmp' type, describing entries in the utmp file.
|
||||||
|
+ Copyright (C) 1993-2019 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
|
||||||
|
@@ -21,29 +21,106 @@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <paths.h>
|
||||||
|
-#include <time.h>
|
||||||
|
+#include <sys/time.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <bits/wordsize.h>
|
||||||
|
|
||||||
|
|
||||||
|
-#define UT_NAMESIZE 8
|
||||||
|
-#define UT_LINESIZE 8
|
||||||
|
-#define UT_HOSTSIZE 16
|
||||||
|
+#define UT_LINESIZE 32
|
||||||
|
+#define UT_NAMESIZE 32
|
||||||
|
+#define UT_HOSTSIZE 256
|
||||||
|
|
||||||
|
|
||||||
|
+/* The structure describing an entry in the database of
|
||||||
|
+ previous logins. */
|
||||||
|
struct lastlog
|
||||||
|
{
|
||||||
|
- time_t ll_time;
|
||||||
|
+#if __WORDSIZE_TIME64_COMPAT32
|
||||||
|
+ int32_t ll_time;
|
||||||
|
+#else
|
||||||
|
+ __time_t ll_time;
|
||||||
|
+#endif
|
||||||
|
char ll_line[UT_LINESIZE];
|
||||||
|
char ll_host[UT_HOSTSIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
-struct utmp
|
||||||
|
+
|
||||||
|
+/* The structure describing the status of a terminated process. This
|
||||||
|
+ type is used in `struct utmp' below. */
|
||||||
|
+struct exit_status
|
||||||
|
{
|
||||||
|
- char ut_line[UT_LINESIZE];
|
||||||
|
- char ut_user[UT_NAMESIZE];
|
||||||
|
-#define ut_name ut_user
|
||||||
|
- char ut_host[UT_HOSTSIZE];
|
||||||
|
- long int ut_time;
|
||||||
|
+ short int e_termination; /* Process termination status. */
|
||||||
|
+ short int e_exit; /* Process exit status. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
-#define _HAVE_UT_HOST 1 /* We have the ut_host field. */
|
||||||
|
+/* The structure describing an entry in the user accounting database. */
|
||||||
|
+struct utmp
|
||||||
|
+{
|
||||||
|
+ short int ut_type; /* Type of login. */
|
||||||
|
+ pid_t ut_pid; /* Process ID of login process. */
|
||||||
|
+ char ut_line[UT_LINESIZE]
|
||||||
|
+ __attribute_nonstring__; /* Devicename. */
|
||||||
|
+ char ut_id[4]; /* Inittab ID. */
|
||||||
|
+ char ut_user[UT_NAMESIZE]
|
||||||
|
+ __attribute_nonstring__; /* Username. */
|
||||||
|
+ char ut_host[UT_HOSTSIZE]
|
||||||
|
+ __attribute_nonstring__; /* Hostname for remote login. */
|
||||||
|
+ struct exit_status ut_exit; /* Exit status of a process marked
|
||||||
|
+ as DEAD_PROCESS. */
|
||||||
|
+/* The ut_session and ut_tv fields must be the same size when compiled
|
||||||
|
+ 32- and 64-bit. This allows data files and shared memory to be
|
||||||
|
+ shared between 32- and 64-bit applications. */
|
||||||
|
+#if __WORDSIZE_TIME64_COMPAT32
|
||||||
|
+ int32_t ut_session; /* Session ID, used for windowing. */
|
||||||
|
+ struct
|
||||||
|
+ {
|
||||||
|
+ int32_t tv_sec; /* Seconds. */
|
||||||
|
+ int32_t tv_usec; /* Microseconds. */
|
||||||
|
+ } ut_tv; /* Time entry was made. */
|
||||||
|
+#else
|
||||||
|
+ long int ut_session; /* Session ID, used for windowing. */
|
||||||
|
+ struct timeval ut_tv; /* Time entry was made. */
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ int32_t ut_addr_v6[4]; /* Internet address of remote host. */
|
||||||
|
+ char __glibc_reserved[20]; /* Reserved for future use. */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Backwards compatibility hacks. */
|
||||||
|
+#define ut_name ut_user
|
||||||
|
+#ifndef _NO_UT_TIME
|
||||||
|
+/* We have a problem here: `ut_time' is also used otherwise. Define
|
||||||
|
+ _NO_UT_TIME if the compiler complains. */
|
||||||
|
+# define ut_time ut_tv.tv_sec
|
||||||
|
+#endif
|
||||||
|
+#define ut_xtime ut_tv.tv_sec
|
||||||
|
+#define ut_addr ut_addr_v6[0]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Values for the `ut_type' field of a `struct utmp'. */
|
||||||
|
+#define EMPTY 0 /* No valid user accounting information. */
|
||||||
|
+
|
||||||
|
+#define RUN_LVL 1 /* The system's runlevel. */
|
||||||
|
+#define BOOT_TIME 2 /* Time of system boot. */
|
||||||
|
+#define NEW_TIME 3 /* Time after system clock changed. */
|
||||||
|
+#define OLD_TIME 4 /* Time when system clock changed. */
|
||||||
|
+
|
||||||
|
+#define INIT_PROCESS 5 /* Process spawned by the init process. */
|
||||||
|
+#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */
|
||||||
|
+#define USER_PROCESS 7 /* Normal process. */
|
||||||
|
+#define DEAD_PROCESS 8 /* Terminated process. */
|
||||||
|
+
|
||||||
|
+#define ACCOUNTING 9
|
||||||
|
+
|
||||||
|
+/* Old Linux name for the EMPTY type. */
|
||||||
|
+#define UT_UNKNOWN EMPTY
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Tell the user that we have a modern system with UT_HOST, UT_PID,
|
||||||
|
+ UT_TYPE, UT_ID and UT_TV fields. */
|
||||||
|
+#define _HAVE_UT_TYPE 1
|
||||||
|
+#define _HAVE_UT_PID 1
|
||||||
|
+#define _HAVE_UT_ID 1
|
||||||
|
+#define _HAVE_UT_TV 1
|
||||||
|
+#define _HAVE_UT_HOST 1
|
||||||
|
diff --git a/login/getutid_r.c b/login/getutid_r.c
|
||||||
|
index 8cb6b16d735e8265..11b288e99be6ee50 100644
|
||||||
|
--- a/login/getutid_r.c
|
||||||
|
+++ b/login/getutid_r.c
|
||||||
|
@@ -32,7 +32,6 @@ __libc_lock_define (extern, __libc_utmp_lock attribute_hidden)
|
||||||
|
int
|
||||||
|
__getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result)
|
||||||
|
{
|
||||||
|
-#if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0)
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
/* Test whether ID has any of the legal types. */
|
||||||
|
@@ -54,10 +53,6 @@ __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result)
|
||||||
|
__libc_lock_unlock (__libc_utmp_lock);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
-#else /* !_HAVE_UT_ID && !_HAVE_UT_TYPE */
|
||||||
|
- __set_errno (ENOSYS);
|
||||||
|
- return -1;
|
||||||
|
-#endif
|
||||||
|
}
|
||||||
|
libc_hidden_def (__getutid_r)
|
||||||
|
weak_alias (__getutid_r, getutid_r)
|
||||||
|
diff --git a/login/getutmp.c b/login/getutmp.c
|
||||||
|
index 481150d5ef5a0bf0..32468ecae699fbf7 100644
|
||||||
|
--- a/login/getutmp.c
|
||||||
|
+++ b/login/getutmp.c
|
||||||
|
@@ -23,23 +23,11 @@
|
||||||
|
void
|
||||||
|
getutmp (const struct utmpx *utmpx, struct utmp *utmp)
|
||||||
|
{
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
utmp->ut_type = utmpx->ut_type;
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_PID - 0
|
||||||
|
utmp->ut_pid = utmpx->ut_pid;
|
||||||
|
-#endif
|
||||||
|
memcpy (utmp->ut_line, utmpx->ut_line, sizeof (utmp->ut_line));
|
||||||
|
memcpy (utmp->ut_user, utmpx->ut_user, sizeof (utmp->ut_user));
|
||||||
|
-#if _HAVE_UT_ID - 0
|
||||||
|
memcpy (utmp->ut_id, utmpx->ut_id, sizeof (utmp->ut_id));
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_HOST - 0
|
||||||
|
memcpy (utmp->ut_host, utmpx->ut_host, sizeof (utmp->ut_host));
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_TV - 0
|
||||||
|
utmp->ut_tv = utmpx->ut_tv;
|
||||||
|
-#else
|
||||||
|
- utmp->ut_time = utmpx->ut_time;
|
||||||
|
-#endif
|
||||||
|
}
|
||||||
|
diff --git a/login/getutmpx.c b/login/getutmpx.c
|
||||||
|
index 34145fe8db71faf0..92a182698e2be438 100644
|
||||||
|
--- a/login/getutmpx.c
|
||||||
|
+++ b/login/getutmpx.c
|
||||||
|
@@ -24,24 +24,11 @@ void
|
||||||
|
getutmpx (const struct utmp *utmp, struct utmpx *utmpx)
|
||||||
|
{
|
||||||
|
memset (utmpx, 0, sizeof (struct utmpx));
|
||||||
|
-
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
utmpx->ut_type = utmp->ut_type;
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_PID - 0
|
||||||
|
utmpx->ut_pid = utmp->ut_pid;
|
||||||
|
-#endif
|
||||||
|
memcpy (utmpx->ut_line, utmp->ut_line, sizeof (utmp->ut_line));
|
||||||
|
memcpy (utmpx->ut_user, utmp->ut_user, sizeof (utmp->ut_user));
|
||||||
|
-#if _HAVE_UT_ID - 0
|
||||||
|
memcpy (utmpx->ut_id, utmp->ut_id, sizeof (utmp->ut_id));
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_HOST - 0
|
||||||
|
memcpy (utmpx->ut_host, utmp->ut_host, sizeof (utmp->ut_host));
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_TV - 0
|
||||||
|
utmpx->ut_tv = utmp->ut_tv;
|
||||||
|
-#else
|
||||||
|
- utmpx->ut_time = utmp->ut_time;
|
||||||
|
-#endif
|
||||||
|
}
|
||||||
|
diff --git a/login/login.c b/login/login.c
|
||||||
|
index 5d48cd487f237ca0..1729fc070fcc1e4b 100644
|
||||||
|
--- a/login/login.c
|
||||||
|
+++ b/login/login.c
|
||||||
|
@@ -91,12 +91,8 @@ login (const struct utmp *ut)
|
||||||
|
struct utmp copy = *ut;
|
||||||
|
|
||||||
|
/* Fill in those fields we supply. */
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
copy.ut_type = USER_PROCESS;
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_PID - 0
|
||||||
|
copy.ut_pid = getpid ();
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
/* Seek tty. */
|
||||||
|
found_tty = tty_name (STDIN_FILENO, &tty, sizeof (_tty));
|
||||||
|
diff --git a/login/logout.c b/login/logout.c
|
||||||
|
index d49bc4ecac9a8379..4d76ecf1b40d306a 100644
|
||||||
|
--- a/login/logout.c
|
||||||
|
+++ b/login/logout.c
|
||||||
|
@@ -36,9 +36,7 @@ logout (const char *line)
|
||||||
|
setutent ();
|
||||||
|
|
||||||
|
/* Fill in search information. */
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
tmp.ut_type = USER_PROCESS;
|
||||||
|
-#endif
|
||||||
|
strncpy (tmp.ut_line, line, sizeof tmp.ut_line);
|
||||||
|
|
||||||
|
/* Read the record. */
|
||||||
|
@@ -46,20 +44,12 @@ logout (const char *line)
|
||||||
|
{
|
||||||
|
/* Clear information about who & from where. */
|
||||||
|
memset (ut->ut_name, '\0', sizeof ut->ut_name);
|
||||||
|
-#if _HAVE_UT_HOST - 0
|
||||||
|
memset (ut->ut_host, '\0', sizeof ut->ut_host);
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_TV - 0
|
||||||
|
struct timeval tv;
|
||||||
|
__gettimeofday (&tv, NULL);
|
||||||
|
ut->ut_tv.tv_sec = tv.tv_sec;
|
||||||
|
ut->ut_tv.tv_usec = tv.tv_usec;
|
||||||
|
-#else
|
||||||
|
- ut->ut_time = time (NULL);
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
ut->ut_type = DEAD_PROCESS;
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
if (pututline (ut) != NULL)
|
||||||
|
result = 1;
|
||||||
|
diff --git a/login/logwtmp.c b/login/logwtmp.c
|
||||||
|
index a19da4ab5ef7a624..e0b52b23e3603b7c 100644
|
||||||
|
--- a/login/logwtmp.c
|
||||||
|
+++ b/login/logwtmp.c
|
||||||
|
@@ -30,26 +30,16 @@ logwtmp (const char *line, const char *name, const char *host)
|
||||||
|
|
||||||
|
/* Set information in new entry. */
|
||||||
|
memset (&ut, 0, sizeof (ut));
|
||||||
|
-#if _HAVE_UT_PID - 0
|
||||||
|
ut.ut_pid = getpid ();
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
ut.ut_type = name[0] ? USER_PROCESS : DEAD_PROCESS;
|
||||||
|
-#endif
|
||||||
|
strncpy (ut.ut_line, line, sizeof ut.ut_line);
|
||||||
|
strncpy (ut.ut_name, name, sizeof ut.ut_name);
|
||||||
|
-#if _HAVE_UT_HOST - 0
|
||||||
|
strncpy (ut.ut_host, host, sizeof ut.ut_host);
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
-#if _HAVE_UT_TV - 0
|
||||||
|
struct timeval tv;
|
||||||
|
__gettimeofday (&tv, NULL);
|
||||||
|
ut.ut_tv.tv_sec = tv.tv_sec;
|
||||||
|
ut.ut_tv.tv_usec = tv.tv_usec;
|
||||||
|
-#else
|
||||||
|
- ut.ut_time = time (NULL);
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
updwtmp (_PATH_WTMP, &ut);
|
||||||
|
}
|
||||||
|
diff --git a/login/programs/utmpdump.c b/login/programs/utmpdump.c
|
||||||
|
index dccdb669f5fb9c74..1763e55af2f03d8d 100644
|
||||||
|
--- a/login/programs/utmpdump.c
|
||||||
|
+++ b/login/programs/utmpdump.c
|
||||||
|
@@ -37,47 +37,11 @@ print_entry (struct utmp *up)
|
||||||
|
temp_tv.tv_sec = up->ut_tv.tv_sec;
|
||||||
|
temp_tv.tv_usec = up->ut_tv.tv_usec;
|
||||||
|
|
||||||
|
- (printf) (
|
||||||
|
- /* The format string. */
|
||||||
|
-#if _HAVE_UT_TYPE
|
||||||
|
- "[%d] "
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_PID
|
||||||
|
- "[%05d] "
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_ID
|
||||||
|
- "[%-4.4s] "
|
||||||
|
-#endif
|
||||||
|
- "[%-8.8s] [%-12.12s]"
|
||||||
|
-#if _HAVE_UT_HOST
|
||||||
|
- " [%-16.16s]"
|
||||||
|
-#endif
|
||||||
|
- " [%-15.15s]"
|
||||||
|
-#if _HAVE_UT_TV
|
||||||
|
- " [%ld]"
|
||||||
|
-#endif
|
||||||
|
- "\n"
|
||||||
|
- /* The arguments. */
|
||||||
|
-#if _HAVE_UT_TYPE
|
||||||
|
- , up->ut_type
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_PID
|
||||||
|
- , up->ut_pid
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_ID
|
||||||
|
- , up->ut_id
|
||||||
|
-#endif
|
||||||
|
- , up->ut_user, up->ut_line
|
||||||
|
-#if _HAVE_UT_HOST
|
||||||
|
- , up->ut_host
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_TV
|
||||||
|
- , 4 + ctime (&temp_tv.tv_sec)
|
||||||
|
- , (long int) temp_tv.tv_usec
|
||||||
|
-#else
|
||||||
|
- , 4 + ctime (&up->ut_time)
|
||||||
|
-#endif
|
||||||
|
- );
|
||||||
|
+ printf ("[%d] [%05d] [%-4.4s] [%-8.8s] [%-12.12s] [%-16.16s] [%-15.15s]"
|
||||||
|
+ " [%ld]\n",
|
||||||
|
+ up->ut_type, up->ut_pid, up->ut_id, up->ut_user, up->ut_line,
|
||||||
|
+ up->ut_host, 4 + ctime (&temp_tv.tv_sec),
|
||||||
|
+ (long int) temp_tv.tv_usec);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
diff --git a/login/tst-utmp.c b/login/tst-utmp.c
|
||||||
|
index 8cc7aafa89c0ea8c..49b0cbda2a719643 100644
|
||||||
|
--- a/login/tst-utmp.c
|
||||||
|
+++ b/login/tst-utmp.c
|
||||||
|
@@ -39,8 +39,6 @@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
-#if defined UTMPX || _HAVE_UT_TYPE
|
||||||
|
-
|
||||||
|
/* Prototype for our test function. */
|
||||||
|
static int do_test (int argc, char *argv[]);
|
||||||
|
|
||||||
|
@@ -75,11 +73,7 @@ do_prepare (int argc, char *argv[])
|
||||||
|
|
||||||
|
struct utmp entry[] =
|
||||||
|
{
|
||||||
|
-#if defined UTMPX || _HAVE_UT_TV
|
||||||
|
#define UT(a) .ut_tv = { .tv_sec = (a)}
|
||||||
|
-#else
|
||||||
|
-#define UT(a) .ut_time = (a)
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
{ .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) },
|
||||||
|
{ .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) },
|
||||||
|
@@ -167,11 +161,7 @@ simulate_login (const char *line, const char *user)
|
||||||
|
entry[n].ut_pid = (entry_pid += 27);
|
||||||
|
entry[n].ut_type = USER_PROCESS;
|
||||||
|
strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user));
|
||||||
|
-#if defined UTMPX || _HAVE_UT_TV - 0
|
||||||
|
entry[n].ut_tv.tv_sec = (entry_time += 1000);
|
||||||
|
-#else
|
||||||
|
- entry[n].ut_time = (entry_time += 1000);
|
||||||
|
-#endif
|
||||||
|
setutent ();
|
||||||
|
|
||||||
|
if (pututline (&entry[n]) == NULL)
|
||||||
|
@@ -201,11 +191,7 @@ simulate_logout (const char *line)
|
||||||
|
{
|
||||||
|
entry[n].ut_type = DEAD_PROCESS;
|
||||||
|
strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user));
|
||||||
|
-#if defined UTMPX || _HAVE_UT_TV - 0
|
||||||
|
entry[n].ut_tv.tv_sec = (entry_time += 1000);
|
||||||
|
-#else
|
||||||
|
- entry[n].ut_time = (entry_time += 1000);
|
||||||
|
-#endif
|
||||||
|
setutent ();
|
||||||
|
|
||||||
|
if (pututline (&entry[n]) == NULL)
|
||||||
|
@@ -390,14 +376,3 @@ do_test (int argc, char *argv[])
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
-#else
|
||||||
|
-
|
||||||
|
-/* No field 'ut_type' in struct utmp. */
|
||||||
|
-int
|
||||||
|
-main (void)
|
||||||
|
-{
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-#endif
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index 069e6d0452e333ad..da1baa6948d0eb39 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -129,14 +129,7 @@ __libc_setutent (void)
|
||||||
|
file_offset = 0;
|
||||||
|
|
||||||
|
/* Make sure the entry won't match. */
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
last_entry.ut_type = -1;
|
||||||
|
-#else
|
||||||
|
- last_entry.ut_line[0] = '\177';
|
||||||
|
-# if _HAVE_UT_ID - 0
|
||||||
|
- last_entry.ut_id[0] = '\0';
|
||||||
|
-# endif
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@@ -201,7 +194,6 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
LOCKING_FAILED ();
|
||||||
|
}
|
||||||
|
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
|
||||||
|
|| id->ut_type == OLD_TIME || id->ut_type == NEW_TIME)
|
||||||
|
{
|
||||||
|
@@ -225,7 +217,6 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
-#endif /* _HAVE_UT_TYPE */
|
||||||
|
{
|
||||||
|
/* Search for the next entry with the specified ID and with type
|
||||||
|
INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS. */
|
||||||
|
@@ -316,13 +307,10 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
file_offset += sizeof (struct utmp);
|
||||||
|
|
||||||
|
/* Stop if we found a user or login entry. */
|
||||||
|
- if (
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
- (last_entry.ut_type == USER_PROCESS
|
||||||
|
+ if ((last_entry.ut_type == USER_PROCESS
|
||||||
|
|| last_entry.ut_type == LOGIN_PROCESS)
|
||||||
|
- &&
|
||||||
|
-#endif
|
||||||
|
- !strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line))
|
||||||
|
+ && (strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line)
|
||||||
|
+ == 0))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -368,16 +356,12 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
|
||||||
|
/* Find the correct place to insert the data. */
|
||||||
|
if (file_offset > 0
|
||||||
|
- && (
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
- (last_entry.ut_type == data->ut_type
|
||||||
|
+ && ((last_entry.ut_type == data->ut_type
|
||||||
|
&& (last_entry.ut_type == RUN_LVL
|
||||||
|
|| last_entry.ut_type == BOOT_TIME
|
||||||
|
|| last_entry.ut_type == OLD_TIME
|
||||||
|
|| last_entry.ut_type == NEW_TIME))
|
||||||
|
- ||
|
||||||
|
-#endif
|
||||||
|
- __utmp_equal (&last_entry, data)))
|
||||||
|
+ || __utmp_equal (&last_entry, data)))
|
||||||
|
found = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff --git a/sysdeps/generic/utmp-equal.h b/sysdeps/generic/utmp-equal.h
|
||||||
|
index 8b5c2e2cd2c4cf95..39993af192ab66ce 100644
|
||||||
|
--- a/sysdeps/generic/utmp-equal.h
|
||||||
|
+++ b/sysdeps/generic/utmp-equal.h
|
||||||
|
@@ -27,26 +27,16 @@
|
||||||
|
static int
|
||||||
|
__utmp_equal (const struct utmp *entry, const struct utmp *match)
|
||||||
|
{
|
||||||
|
- return
|
||||||
|
- (
|
||||||
|
-#if _HAVE_UT_TYPE - 0
|
||||||
|
- (entry->ut_type == INIT_PROCESS
|
||||||
|
- || entry->ut_type == LOGIN_PROCESS
|
||||||
|
- || entry->ut_type == USER_PROCESS
|
||||||
|
- || entry->ut_type == DEAD_PROCESS)
|
||||||
|
- &&
|
||||||
|
- (match->ut_type == INIT_PROCESS
|
||||||
|
- || match->ut_type == LOGIN_PROCESS
|
||||||
|
- || match->ut_type == USER_PROCESS
|
||||||
|
- || match->ut_type == DEAD_PROCESS)
|
||||||
|
- &&
|
||||||
|
-#endif
|
||||||
|
-#if _HAVE_UT_ID - 0
|
||||||
|
- (entry->ut_id[0] && match->ut_id[0]
|
||||||
|
- ? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0
|
||||||
|
- : strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0)
|
||||||
|
-#else
|
||||||
|
- strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0
|
||||||
|
-#endif
|
||||||
|
- );
|
||||||
|
+ return (entry->ut_type == INIT_PROCESS
|
||||||
|
+ || entry->ut_type == LOGIN_PROCESS
|
||||||
|
+ || entry->ut_type == USER_PROCESS
|
||||||
|
+ || entry->ut_type == DEAD_PROCESS)
|
||||||
|
+ && (match->ut_type == INIT_PROCESS
|
||||||
|
+ || match->ut_type == LOGIN_PROCESS
|
||||||
|
+ || match->ut_type == USER_PROCESS
|
||||||
|
+ || match->ut_type == DEAD_PROCESS)
|
||||||
|
+ && (entry->ut_id[0] && match->ut_id[0]
|
||||||
|
+ ? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0
|
||||||
|
+ : (strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line)
|
||||||
|
+ == 0));
|
||||||
|
}
|
||||||
|
diff --git a/sysdeps/gnu/bits/utmp.h b/sysdeps/gnu/bits/utmp.h
|
||||||
|
deleted file mode 100644
|
||||||
|
index 47a6082eacc56b4d..0000000000000000
|
||||||
|
--- a/sysdeps/gnu/bits/utmp.h
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,126 +0,0 @@
|
||||||
|
-/* The `struct utmp' type, describing entries in the utmp file. GNU version.
|
||||||
|
- Copyright (C) 1993-2018 Free Software Foundation, Inc.
|
||||||
|
- This file is part of the GNU C Library.
|
||||||
|
-
|
||||||
|
- The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
- modify it under the terms of the GNU Lesser General Public
|
||||||
|
- License as published by the Free Software Foundation; either
|
||||||
|
- version 2.1 of the License, or (at your option) any later version.
|
||||||
|
-
|
||||||
|
- The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
- Lesser General Public License for more details.
|
||||||
|
-
|
||||||
|
- You should have received a copy of the GNU Lesser General Public
|
||||||
|
- License along with the GNU C Library; if not, see
|
||||||
|
- <http://www.gnu.org/licenses/>. */
|
||||||
|
-
|
||||||
|
-#ifndef _UTMP_H
|
||||||
|
-# error "Never include <bits/utmp.h> directly; use <utmp.h> instead."
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
-#include <paths.h>
|
||||||
|
-#include <sys/time.h>
|
||||||
|
-#include <sys/types.h>
|
||||||
|
-#include <bits/wordsize.h>
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-#define UT_LINESIZE 32
|
||||||
|
-#define UT_NAMESIZE 32
|
||||||
|
-#define UT_HOSTSIZE 256
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* The structure describing an entry in the database of
|
||||||
|
- previous logins. */
|
||||||
|
-struct lastlog
|
||||||
|
- {
|
||||||
|
-#if __WORDSIZE_TIME64_COMPAT32
|
||||||
|
- int32_t ll_time;
|
||||||
|
-#else
|
||||||
|
- __time_t ll_time;
|
||||||
|
-#endif
|
||||||
|
- char ll_line[UT_LINESIZE];
|
||||||
|
- char ll_host[UT_HOSTSIZE];
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* The structure describing the status of a terminated process. This
|
||||||
|
- type is used in `struct utmp' below. */
|
||||||
|
-struct exit_status
|
||||||
|
- {
|
||||||
|
- short int e_termination; /* Process termination status. */
|
||||||
|
- short int e_exit; /* Process exit status. */
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* The structure describing an entry in the user accounting database. */
|
||||||
|
-struct utmp
|
||||||
|
-{
|
||||||
|
- short int ut_type; /* Type of login. */
|
||||||
|
- pid_t ut_pid; /* Process ID of login process. */
|
||||||
|
- char ut_line[UT_LINESIZE]
|
||||||
|
- __attribute_nonstring__; /* Devicename. */
|
||||||
|
- char ut_id[4]; /* Inittab ID. */
|
||||||
|
- char ut_user[UT_NAMESIZE]
|
||||||
|
- __attribute_nonstring__; /* Username. */
|
||||||
|
- char ut_host[UT_HOSTSIZE]
|
||||||
|
- __attribute_nonstring__; /* Hostname for remote login. */
|
||||||
|
- struct exit_status ut_exit; /* Exit status of a process marked
|
||||||
|
- as DEAD_PROCESS. */
|
||||||
|
-/* The ut_session and ut_tv fields must be the same size when compiled
|
||||||
|
- 32- and 64-bit. This allows data files and shared memory to be
|
||||||
|
- shared between 32- and 64-bit applications. */
|
||||||
|
-#if __WORDSIZE_TIME64_COMPAT32
|
||||||
|
- int32_t ut_session; /* Session ID, used for windowing. */
|
||||||
|
- struct
|
||||||
|
- {
|
||||||
|
- int32_t tv_sec; /* Seconds. */
|
||||||
|
- int32_t tv_usec; /* Microseconds. */
|
||||||
|
- } ut_tv; /* Time entry was made. */
|
||||||
|
-#else
|
||||||
|
- long int ut_session; /* Session ID, used for windowing. */
|
||||||
|
- struct timeval ut_tv; /* Time entry was made. */
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
- int32_t ut_addr_v6[4]; /* Internet address of remote host. */
|
||||||
|
- char __glibc_reserved[20]; /* Reserved for future use. */
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-/* Backwards compatibility hacks. */
|
||||||
|
-#define ut_name ut_user
|
||||||
|
-#ifndef _NO_UT_TIME
|
||||||
|
-/* We have a problem here: `ut_time' is also used otherwise. Define
|
||||||
|
- _NO_UT_TIME if the compiler complains. */
|
||||||
|
-# define ut_time ut_tv.tv_sec
|
||||||
|
-#endif
|
||||||
|
-#define ut_xtime ut_tv.tv_sec
|
||||||
|
-#define ut_addr ut_addr_v6[0]
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* Values for the `ut_type' field of a `struct utmp'. */
|
||||||
|
-#define EMPTY 0 /* No valid user accounting information. */
|
||||||
|
-
|
||||||
|
-#define RUN_LVL 1 /* The system's runlevel. */
|
||||||
|
-#define BOOT_TIME 2 /* Time of system boot. */
|
||||||
|
-#define NEW_TIME 3 /* Time after system clock changed. */
|
||||||
|
-#define OLD_TIME 4 /* Time when system clock changed. */
|
||||||
|
-
|
||||||
|
-#define INIT_PROCESS 5 /* Process spawned by the init process. */
|
||||||
|
-#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */
|
||||||
|
-#define USER_PROCESS 7 /* Normal process. */
|
||||||
|
-#define DEAD_PROCESS 8 /* Terminated process. */
|
||||||
|
-
|
||||||
|
-#define ACCOUNTING 9
|
||||||
|
-
|
||||||
|
-/* Old Linux name for the EMPTY type. */
|
||||||
|
-#define UT_UNKNOWN EMPTY
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* Tell the user that we have a modern system with UT_HOST, UT_PID,
|
||||||
|
- UT_TYPE, UT_ID and UT_TV fields. */
|
||||||
|
-#define _HAVE_UT_TYPE 1
|
||||||
|
-#define _HAVE_UT_PID 1
|
||||||
|
-#define _HAVE_UT_ID 1
|
||||||
|
-#define _HAVE_UT_TV 1
|
||||||
|
-#define _HAVE_UT_HOST 1
|
260
SOURCES/glibc-rh1749439-3.patch
Normal file
260
SOURCES/glibc-rh1749439-3.patch
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
commit 5a3afa9738f3dbbaf8c0a35665318c1af782111b
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Tue Aug 13 15:53:19 2019 +0200
|
||||||
|
|
||||||
|
login: Replace macro-based control flow with function calls in utmp
|
||||||
|
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index da1baa6948d0eb39..812de8fd3d099ce9 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -52,58 +52,71 @@ static struct utmp last_entry;
|
||||||
|
/* Do-nothing handler for locking timeout. */
|
||||||
|
static void timeout_handler (int signum) {};
|
||||||
|
|
||||||
|
-/* LOCK_FILE(fd, type) failure_statement
|
||||||
|
- attempts to get a lock on the utmp file referenced by FD. If it fails,
|
||||||
|
- the failure_statement is executed, otherwise it is skipped.
|
||||||
|
- LOCKING_FAILED()
|
||||||
|
- jumps into the UNLOCK_FILE macro and ensures cleanup of LOCK_FILE.
|
||||||
|
- UNLOCK_FILE(fd)
|
||||||
|
- unlocks the utmp file referenced by FD and performs the cleanup of
|
||||||
|
- LOCK_FILE.
|
||||||
|
- */
|
||||||
|
-#define LOCK_FILE(fd, type) \
|
||||||
|
-{ \
|
||||||
|
- struct flock fl; \
|
||||||
|
- struct sigaction action, old_action; \
|
||||||
|
- unsigned int old_timeout; \
|
||||||
|
- \
|
||||||
|
- /* Cancel any existing alarm. */ \
|
||||||
|
- old_timeout = alarm (0); \
|
||||||
|
- \
|
||||||
|
- /* Establish signal handler. */ \
|
||||||
|
- action.sa_handler = timeout_handler; \
|
||||||
|
- __sigemptyset (&action.sa_mask); \
|
||||||
|
- action.sa_flags = 0; \
|
||||||
|
- __sigaction (SIGALRM, &action, &old_action); \
|
||||||
|
- \
|
||||||
|
- alarm (TIMEOUT); \
|
||||||
|
- \
|
||||||
|
- /* Try to get the lock. */ \
|
||||||
|
- memset (&fl, '\0', sizeof (struct flock)); \
|
||||||
|
- fl.l_type = (type); \
|
||||||
|
- fl.l_whence = SEEK_SET; \
|
||||||
|
- if (__fcntl64_nocancel ((fd), F_SETLKW, &fl) < 0)
|
||||||
|
-
|
||||||
|
-#define LOCKING_FAILED() \
|
||||||
|
- goto unalarm_return
|
||||||
|
-
|
||||||
|
-#define UNLOCK_FILE(fd) \
|
||||||
|
- /* Unlock the file. */ \
|
||||||
|
- fl.l_type = F_UNLCK; \
|
||||||
|
- __fcntl64_nocancel ((fd), F_SETLKW, &fl); \
|
||||||
|
- \
|
||||||
|
- unalarm_return: \
|
||||||
|
- /* Reset the signal handler and alarm. We must reset the alarm \
|
||||||
|
- before resetting the handler so our alarm does not generate a \
|
||||||
|
- spurious SIGALRM seen by the user. However, we cannot just set \
|
||||||
|
- the user's old alarm before restoring the handler, because then \
|
||||||
|
- it's possible our handler could catch the user alarm's SIGARLM \
|
||||||
|
- and then the user would never see the signal he expected. */ \
|
||||||
|
- alarm (0); \
|
||||||
|
- __sigaction (SIGALRM, &old_action, NULL); \
|
||||||
|
- if (old_timeout != 0) \
|
||||||
|
- alarm (old_timeout); \
|
||||||
|
-} while (0)
|
||||||
|
+
|
||||||
|
+/* try_file_lock (LOCKING, FD, TYPE) returns true if the locking
|
||||||
|
+ operation failed and recovery needs to be performed.
|
||||||
|
+ (file_lock_restore (LOCKING) still needs to be called.)
|
||||||
|
+
|
||||||
|
+ file_unlock (FD) removes the lock (which must have been
|
||||||
|
+ acquired).
|
||||||
|
+
|
||||||
|
+ file_lock_restore (LOCKING) is needed to clean up in both
|
||||||
|
+ cases. */
|
||||||
|
+
|
||||||
|
+struct file_locking
|
||||||
|
+{
|
||||||
|
+ struct sigaction old_action;
|
||||||
|
+ unsigned int old_timeout;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+try_file_lock (struct file_locking *locking, int fd, int type)
|
||||||
|
+{
|
||||||
|
+ /* Cancel any existing alarm. */
|
||||||
|
+ locking->old_timeout = alarm (0);
|
||||||
|
+
|
||||||
|
+ /* Establish signal handler. */
|
||||||
|
+ struct sigaction action;
|
||||||
|
+ action.sa_handler = timeout_handler;
|
||||||
|
+ __sigemptyset (&action.sa_mask);
|
||||||
|
+ action.sa_flags = 0;
|
||||||
|
+ __sigaction (SIGALRM, &action, &locking->old_action);
|
||||||
|
+
|
||||||
|
+ alarm (TIMEOUT);
|
||||||
|
+
|
||||||
|
+ /* Try to get the lock. */
|
||||||
|
+ struct flock fl =
|
||||||
|
+ {
|
||||||
|
+ .l_type = type,
|
||||||
|
+ fl.l_whence = SEEK_SET,
|
||||||
|
+ };
|
||||||
|
+ return __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+file_unlock (int fd)
|
||||||
|
+{
|
||||||
|
+ struct flock fl =
|
||||||
|
+ {
|
||||||
|
+ .l_type = F_UNLCK,
|
||||||
|
+ };
|
||||||
|
+ __fcntl64_nocancel (fd, F_SETLKW, &fl);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+file_lock_restore (struct file_locking *locking)
|
||||||
|
+{
|
||||||
|
+ /* Reset the signal handler and alarm. We must reset the alarm
|
||||||
|
+ before resetting the handler so our alarm does not generate a
|
||||||
|
+ spurious SIGALRM seen by the user. However, we cannot just set
|
||||||
|
+ the user's old alarm before restoring the handler, because then
|
||||||
|
+ it's possible our handler could catch the user alarm's SIGARLM
|
||||||
|
+ and then the user would never see the signal he expected. */
|
||||||
|
+ alarm (0);
|
||||||
|
+ __sigaction (SIGALRM, &locking->old_action, NULL);
|
||||||
|
+ if (locking->old_timeout != 0)
|
||||||
|
+ alarm (locking->old_timeout);
|
||||||
|
+}
|
||||||
|
|
||||||
|
#ifndef TRANSFORM_UTMP_FILE_NAME
|
||||||
|
# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name)
|
||||||
|
@@ -153,16 +166,16 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- LOCK_FILE (file_fd, F_RDLCK)
|
||||||
|
+ struct file_locking fl;
|
||||||
|
+ if (try_file_lock (&fl, file_fd, F_RDLCK))
|
||||||
|
+ nbytes = 0;
|
||||||
|
+ else
|
||||||
|
{
|
||||||
|
- nbytes = 0;
|
||||||
|
- LOCKING_FAILED ();
|
||||||
|
+ /* Read the next entry. */
|
||||||
|
+ nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp));
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- /* Read the next entry. */
|
||||||
|
- nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp));
|
||||||
|
-
|
||||||
|
- UNLOCK_FILE (file_fd);
|
||||||
|
+ file_lock_restore (&fl);
|
||||||
|
|
||||||
|
if (nbytes != sizeof (struct utmp))
|
||||||
|
{
|
||||||
|
@@ -188,10 +201,12 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
- LOCK_FILE (file_fd, F_RDLCK)
|
||||||
|
+ struct file_locking fl;
|
||||||
|
+ if (try_file_lock (&fl, file_fd, F_RDLCK))
|
||||||
|
{
|
||||||
|
*lock_failed = true;
|
||||||
|
- LOCKING_FAILED ();
|
||||||
|
+ file_lock_restore (&fl);
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
|
||||||
|
@@ -241,7 +256,8 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
unlock_return:
|
||||||
|
- UNLOCK_FILE (file_fd);
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
+ file_lock_restore (&fl);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@@ -287,10 +303,12 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- LOCK_FILE (file_fd, F_RDLCK)
|
||||||
|
+ struct file_locking fl;
|
||||||
|
+ if (try_file_lock (&fl, file_fd, F_RDLCK))
|
||||||
|
{
|
||||||
|
*result = NULL;
|
||||||
|
- LOCKING_FAILED ();
|
||||||
|
+ file_lock_restore (&fl);
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
@@ -318,7 +336,8 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
*result = buffer;
|
||||||
|
|
||||||
|
unlock_return:
|
||||||
|
- UNLOCK_FILE (file_fd);
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
+ file_lock_restore (&fl);
|
||||||
|
|
||||||
|
return ((*result == NULL) ? -1 : 0);
|
||||||
|
}
|
||||||
|
@@ -375,10 +394,11 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- LOCK_FILE (file_fd, F_WRLCK)
|
||||||
|
+ struct file_locking fl;
|
||||||
|
+ if (try_file_lock (&fl, file_fd, F_WRLCK))
|
||||||
|
{
|
||||||
|
- pbuf = NULL;
|
||||||
|
- LOCKING_FAILED ();
|
||||||
|
+ file_lock_restore (&fl);
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found < 0)
|
||||||
|
@@ -421,7 +441,8 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_return:
|
||||||
|
- UNLOCK_FILE (file_fd);
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
+ file_lock_restore (&fl);
|
||||||
|
|
||||||
|
return pbuf;
|
||||||
|
}
|
||||||
|
@@ -450,8 +471,13 @@ __libc_updwtmp (const char *file, const struct utmp *utmp)
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
- LOCK_FILE (fd, F_WRLCK)
|
||||||
|
- LOCKING_FAILED ();
|
||||||
|
+ struct file_locking fl;
|
||||||
|
+ if (try_file_lock (&fl, fd, F_WRLCK))
|
||||||
|
+ {
|
||||||
|
+ file_lock_restore (&fl);
|
||||||
|
+ __close_nocancel_nostatus (fd);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Remember original size of log file. */
|
||||||
|
offset = __lseek64 (fd, 0, SEEK_END);
|
||||||
|
@@ -477,7 +503,8 @@ __libc_updwtmp (const char *file, const struct utmp *utmp)
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
unlock_return:
|
||||||
|
- UNLOCK_FILE (fd);
|
||||||
|
+ file_unlock (file_fd);
|
||||||
|
+ file_lock_restore (&fl);
|
||||||
|
|
||||||
|
/* Close WTMP file. */
|
||||||
|
__close_nocancel_nostatus (fd);
|
155
SOURCES/glibc-rh1749439-4.patch
Normal file
155
SOURCES/glibc-rh1749439-4.patch
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
commit 341da5b4b6253de9a7581a066f33f89cacb44dec
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Aug 15 10:30:23 2019 +0200
|
||||||
|
|
||||||
|
login: Fix updwtmp, updwtmx unlocking
|
||||||
|
|
||||||
|
Commit 5a3afa9738f3dbbaf8c0a35665318c1af782111b (login: Replace
|
||||||
|
macro-based control flow with function calls in utmp) introduced
|
||||||
|
a regression because after it, __libc_updwtmp attempts to unlock
|
||||||
|
the wrong file descriptor.
|
||||||
|
|
||||||
|
diff --git a/login/Makefile b/login/Makefile
|
||||||
|
index 8b31991be835fa8e..81986ab6bd8560ea 100644
|
||||||
|
--- a/login/Makefile
|
||||||
|
+++ b/login/Makefile
|
||||||
|
@@ -43,7 +43,7 @@ endif
|
||||||
|
subdir-dirs = programs
|
||||||
|
vpath %.c programs
|
||||||
|
|
||||||
|
-tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin
|
||||||
|
+tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx
|
||||||
|
|
||||||
|
# Build the -lutil library with these extra functions.
|
||||||
|
extra-libs := libutil
|
||||||
|
diff --git a/login/tst-updwtmpx.c b/login/tst-updwtmpx.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..0a4a27daeb0440fd
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/login/tst-updwtmpx.c
|
||||||
|
@@ -0,0 +1,112 @@
|
||||||
|
+/* Basic test coverage for updwtmpx.
|
||||||
|
+ Copyright (C) 2019 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; see the file COPYING.LIB. If
|
||||||
|
+ not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* This program runs a series of tests. Each one calls updwtmpx
|
||||||
|
+ twice, to write two records, optionally with misalignment in the
|
||||||
|
+ file, and reads back the results. */
|
||||||
|
+
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/descriptors.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/temp_file.h>
|
||||||
|
+#include <support/test-driver.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <utmpx.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* Two entries filled with an arbitrary bit pattern. */
|
||||||
|
+ struct utmpx entries[2];
|
||||||
|
+ unsigned char pad;
|
||||||
|
+ {
|
||||||
|
+ unsigned char *p = (unsigned char *) &entries[0];
|
||||||
|
+ for (size_t i = 0; i < sizeof (entries); ++i)
|
||||||
|
+ {
|
||||||
|
+ p[i] = i;
|
||||||
|
+ }
|
||||||
|
+ /* Make sure that the first and second entry and the padding are
|
||||||
|
+ different. */
|
||||||
|
+ p[sizeof (struct utmpx)] = p[0] + 1;
|
||||||
|
+ pad = p[0] + 2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ char *path;
|
||||||
|
+ int fd = create_temp_file ("tst-updwtmpx-", &path);
|
||||||
|
+
|
||||||
|
+ /* Used to check that updwtmpx does not leave an open file
|
||||||
|
+ descriptor around. */
|
||||||
|
+ struct support_descriptors *descriptors = support_descriptors_list ();
|
||||||
|
+
|
||||||
|
+ /* updwtmpx is expected to remove misalignment. Optionally insert
|
||||||
|
+ one byte of misalignment at the start and in the middle (after
|
||||||
|
+ the first entry). */
|
||||||
|
+ for (int misaligned_start = 0; misaligned_start < 2; ++misaligned_start)
|
||||||
|
+ for (int misaligned_middle = 0; misaligned_middle < 2; ++misaligned_middle)
|
||||||
|
+ {
|
||||||
|
+ if (test_verbose > 0)
|
||||||
|
+ printf ("info: misaligned_start=%d misaligned_middle=%d\n",
|
||||||
|
+ misaligned_start, misaligned_middle);
|
||||||
|
+
|
||||||
|
+ xftruncate (fd, 0);
|
||||||
|
+ TEST_COMPARE (pwrite64 (fd, &pad, misaligned_start, 0),
|
||||||
|
+ misaligned_start);
|
||||||
|
+
|
||||||
|
+ /* Write first entry and check it. */
|
||||||
|
+ errno = 0;
|
||||||
|
+ updwtmpx (path, &entries[0]);
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+ support_descriptors_check (descriptors);
|
||||||
|
+ TEST_COMPARE (xlseek (fd, 0, SEEK_END), sizeof (struct utmpx));
|
||||||
|
+ struct utmpx buffer;
|
||||||
|
+ TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0),
|
||||||
|
+ sizeof (buffer));
|
||||||
|
+ TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]),
|
||||||
|
+ &buffer, sizeof (buffer));
|
||||||
|
+
|
||||||
|
+ /* Middle mis-alignmet. */
|
||||||
|
+ TEST_COMPARE (pwrite64 (fd, &pad, misaligned_middle,
|
||||||
|
+ sizeof (struct utmpx)), misaligned_middle);
|
||||||
|
+
|
||||||
|
+ /* Write second entry and check both entries. */
|
||||||
|
+ errno = 0;
|
||||||
|
+ updwtmpx (path, &entries[1]);
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+ support_descriptors_check (descriptors);
|
||||||
|
+ TEST_COMPARE (xlseek (fd, 0, SEEK_END), 2 * sizeof (struct utmpx));
|
||||||
|
+ TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0),
|
||||||
|
+ sizeof (buffer));
|
||||||
|
+ TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]),
|
||||||
|
+ &buffer, sizeof (buffer));
|
||||||
|
+ TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), sizeof (buffer)),
|
||||||
|
+ sizeof (buffer));
|
||||||
|
+ TEST_COMPARE_BLOB (&entries[1], sizeof (entries[1]),
|
||||||
|
+ &buffer, sizeof (buffer));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ support_descriptors_free (descriptors);
|
||||||
|
+ free (path);
|
||||||
|
+ xclose (fd);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index 812de8fd3d099ce9..54f424fd6165bae7 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -503,7 +503,7 @@ __libc_updwtmp (const char *file, const struct utmp *utmp)
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
unlock_return:
|
||||||
|
- file_unlock (file_fd);
|
||||||
|
+ file_unlock (fd);
|
||||||
|
file_lock_restore (&fl);
|
||||||
|
|
||||||
|
/* Close WTMP file. */
|
33
SOURCES/glibc-rh1749439-5.patch
Normal file
33
SOURCES/glibc-rh1749439-5.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
commit 0d5b2917530ccaf8ad312dfbb7bce69d569c23ad
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Aug 15 16:09:20 2019 +0200
|
||||||
|
|
||||||
|
login: Use struct flock64 in utmp [BZ #24880]
|
||||||
|
|
||||||
|
Commit 06ab719d30b01da401150068054d3b8ea93dd12f ("Fix Linux fcntl OFD
|
||||||
|
locks for non-LFS architectures (BZ#20251)") introduced the use of
|
||||||
|
fcntl64 into the utmp implementation. However, the lock file
|
||||||
|
structure was not updated to struct flock64 at that point.
|
||||||
|
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index 54f424fd6165bae7..8b6fee96b623fa90 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -85,7 +85,7 @@ try_file_lock (struct file_locking *locking, int fd, int type)
|
||||||
|
alarm (TIMEOUT);
|
||||||
|
|
||||||
|
/* Try to get the lock. */
|
||||||
|
- struct flock fl =
|
||||||
|
+ struct flock64 fl =
|
||||||
|
{
|
||||||
|
.l_type = type,
|
||||||
|
fl.l_whence = SEEK_SET,
|
||||||
|
@@ -96,7 +96,7 @@ try_file_lock (struct file_locking *locking, int fd, int type)
|
||||||
|
static void
|
||||||
|
file_unlock (int fd)
|
||||||
|
{
|
||||||
|
- struct flock fl =
|
||||||
|
+ struct flock64 fl =
|
||||||
|
{
|
||||||
|
.l_type = F_UNLCK,
|
||||||
|
};
|
204
SOURCES/glibc-rh1749439-6.patch
Normal file
204
SOURCES/glibc-rh1749439-6.patch
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
commit 628598be7e1bfaa04f34df71ef6678f2c5103dfd
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Aug 15 16:09:05 2019 +0200
|
||||||
|
|
||||||
|
login: Disarm timer after utmp lock acquisition [BZ #24879]
|
||||||
|
|
||||||
|
If the file processing takes a long time for some reason, SIGALRM can
|
||||||
|
arrive while the file is still being processed. At that point, file
|
||||||
|
access will fail with EINTR. Disarming the timer after lock
|
||||||
|
acquisition avoids that. (If there was a previous alarm, it is the
|
||||||
|
responsibility of the caller to deal with the EINTR error.)
|
||||||
|
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index 8b6fee96b623fa90..a736d3d25e005920 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -55,32 +55,23 @@ static void timeout_handler (int signum) {};
|
||||||
|
|
||||||
|
/* try_file_lock (LOCKING, FD, TYPE) returns true if the locking
|
||||||
|
operation failed and recovery needs to be performed.
|
||||||
|
- (file_lock_restore (LOCKING) still needs to be called.)
|
||||||
|
|
||||||
|
file_unlock (FD) removes the lock (which must have been
|
||||||
|
- acquired).
|
||||||
|
-
|
||||||
|
- file_lock_restore (LOCKING) is needed to clean up in both
|
||||||
|
- cases. */
|
||||||
|
-
|
||||||
|
-struct file_locking
|
||||||
|
-{
|
||||||
|
- struct sigaction old_action;
|
||||||
|
- unsigned int old_timeout;
|
||||||
|
-};
|
||||||
|
+ successfully acquired). */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
-try_file_lock (struct file_locking *locking, int fd, int type)
|
||||||
|
+try_file_lock (int fd, int type)
|
||||||
|
{
|
||||||
|
/* Cancel any existing alarm. */
|
||||||
|
- locking->old_timeout = alarm (0);
|
||||||
|
+ int old_timeout = alarm (0);
|
||||||
|
|
||||||
|
/* Establish signal handler. */
|
||||||
|
+ struct sigaction old_action;
|
||||||
|
struct sigaction action;
|
||||||
|
action.sa_handler = timeout_handler;
|
||||||
|
__sigemptyset (&action.sa_mask);
|
||||||
|
action.sa_flags = 0;
|
||||||
|
- __sigaction (SIGALRM, &action, &locking->old_action);
|
||||||
|
+ __sigaction (SIGALRM, &action, &old_action);
|
||||||
|
|
||||||
|
alarm (TIMEOUT);
|
||||||
|
|
||||||
|
@@ -90,7 +81,23 @@ try_file_lock (struct file_locking *locking, int fd, int type)
|
||||||
|
.l_type = type,
|
||||||
|
fl.l_whence = SEEK_SET,
|
||||||
|
};
|
||||||
|
- return __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0;
|
||||||
|
+
|
||||||
|
+ bool status = __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0;
|
||||||
|
+ int saved_errno = errno;
|
||||||
|
+
|
||||||
|
+ /* Reset the signal handler and alarm. We must reset the alarm
|
||||||
|
+ before resetting the handler so our alarm does not generate a
|
||||||
|
+ spurious SIGALRM seen by the user. However, we cannot just set
|
||||||
|
+ the user's old alarm before restoring the handler, because then
|
||||||
|
+ it's possible our handler could catch the user alarm's SIGARLM and
|
||||||
|
+ then the user would never see the signal he expected. */
|
||||||
|
+ alarm (0);
|
||||||
|
+ __sigaction (SIGALRM, &old_action, NULL);
|
||||||
|
+ if (old_timeout != 0)
|
||||||
|
+ alarm (old_timeout);
|
||||||
|
+
|
||||||
|
+ __set_errno (saved_errno);
|
||||||
|
+ return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -103,21 +110,6 @@ file_unlock (int fd)
|
||||||
|
__fcntl64_nocancel (fd, F_SETLKW, &fl);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-file_lock_restore (struct file_locking *locking)
|
||||||
|
-{
|
||||||
|
- /* Reset the signal handler and alarm. We must reset the alarm
|
||||||
|
- before resetting the handler so our alarm does not generate a
|
||||||
|
- spurious SIGALRM seen by the user. However, we cannot just set
|
||||||
|
- the user's old alarm before restoring the handler, because then
|
||||||
|
- it's possible our handler could catch the user alarm's SIGARLM
|
||||||
|
- and then the user would never see the signal he expected. */
|
||||||
|
- alarm (0);
|
||||||
|
- __sigaction (SIGALRM, &locking->old_action, NULL);
|
||||||
|
- if (locking->old_timeout != 0)
|
||||||
|
- alarm (locking->old_timeout);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
#ifndef TRANSFORM_UTMP_FILE_NAME
|
||||||
|
# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name)
|
||||||
|
#endif
|
||||||
|
@@ -166,8 +158,7 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- struct file_locking fl;
|
||||||
|
- if (try_file_lock (&fl, file_fd, F_RDLCK))
|
||||||
|
+ if (try_file_lock (file_fd, F_RDLCK))
|
||||||
|
nbytes = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@@ -175,7 +166,6 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp));
|
||||||
|
file_unlock (file_fd);
|
||||||
|
}
|
||||||
|
- file_lock_restore (&fl);
|
||||||
|
|
||||||
|
if (nbytes != sizeof (struct utmp))
|
||||||
|
{
|
||||||
|
@@ -201,11 +191,9 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
- struct file_locking fl;
|
||||||
|
- if (try_file_lock (&fl, file_fd, F_RDLCK))
|
||||||
|
+ if (try_file_lock (file_fd, F_RDLCK))
|
||||||
|
{
|
||||||
|
*lock_failed = true;
|
||||||
|
- file_lock_restore (&fl);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -257,7 +245,6 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
|
||||||
|
unlock_return:
|
||||||
|
file_unlock (file_fd);
|
||||||
|
- file_lock_restore (&fl);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@@ -303,11 +290,9 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- struct file_locking fl;
|
||||||
|
- if (try_file_lock (&fl, file_fd, F_RDLCK))
|
||||||
|
+ if (try_file_lock (file_fd, F_RDLCK))
|
||||||
|
{
|
||||||
|
*result = NULL;
|
||||||
|
- file_lock_restore (&fl);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -337,7 +322,6 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||||
|
|
||||||
|
unlock_return:
|
||||||
|
file_unlock (file_fd);
|
||||||
|
- file_lock_restore (&fl);
|
||||||
|
|
||||||
|
return ((*result == NULL) ? -1 : 0);
|
||||||
|
}
|
||||||
|
@@ -394,12 +378,8 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- struct file_locking fl;
|
||||||
|
- if (try_file_lock (&fl, file_fd, F_WRLCK))
|
||||||
|
- {
|
||||||
|
- file_lock_restore (&fl);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
+ if (try_file_lock (file_fd, F_WRLCK))
|
||||||
|
+ return NULL;
|
||||||
|
|
||||||
|
if (found < 0)
|
||||||
|
{
|
||||||
|
@@ -442,7 +422,6 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
|
||||||
|
unlock_return:
|
||||||
|
file_unlock (file_fd);
|
||||||
|
- file_lock_restore (&fl);
|
||||||
|
|
||||||
|
return pbuf;
|
||||||
|
}
|
||||||
|
@@ -471,10 +450,8 @@ __libc_updwtmp (const char *file, const struct utmp *utmp)
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
- struct file_locking fl;
|
||||||
|
- if (try_file_lock (&fl, fd, F_WRLCK))
|
||||||
|
+ if (try_file_lock (fd, F_WRLCK))
|
||||||
|
{
|
||||||
|
- file_lock_restore (&fl);
|
||||||
|
__close_nocancel_nostatus (fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@@ -504,7 +481,6 @@ __libc_updwtmp (const char *file, const struct utmp *utmp)
|
||||||
|
|
||||||
|
unlock_return:
|
||||||
|
file_unlock (fd);
|
||||||
|
- file_lock_restore (&fl);
|
||||||
|
|
||||||
|
/* Close WTMP file. */
|
||||||
|
__close_nocancel_nostatus (fd);
|
309
SOURCES/glibc-rh1749439-7.patch
Normal file
309
SOURCES/glibc-rh1749439-7.patch
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
commit 61d3db428176d9d0822e4e680305fe34285edff2
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Aug 28 11:59:45 2019 +0200
|
||||||
|
|
||||||
|
login: pututxline could fail to overwrite existing entries [BZ #24902]
|
||||||
|
|
||||||
|
The internal_getut_r function updates the file_offset variable and
|
||||||
|
therefore must always update last_entry as well.
|
||||||
|
|
||||||
|
Previously, if pututxline could not upgrade the read lock to a
|
||||||
|
write lock, internal_getut_r would update file_offset only,
|
||||||
|
without updating last_entry, and a subsequent call would not
|
||||||
|
overwrite the existing utmpx entry at file_offset, instead
|
||||||
|
creating a new entry. This has been observed to cause unbounded
|
||||||
|
file growth in high-load situations.
|
||||||
|
|
||||||
|
This commit removes the buffer argument to internal_getut_r and
|
||||||
|
updates the last_entry variable directly, along with file_offset.
|
||||||
|
|
||||||
|
Initially reported and fixed by Ondřej Lysoněk.
|
||||||
|
|
||||||
|
Reviewed-by: Gabriel F. T. Gomes <gabrielftg@linux.ibm.com>
|
||||||
|
|
||||||
|
diff --git a/login/Makefile b/login/Makefile
|
||||||
|
index 81986ab6bd8560ea..82132c83fd799357 100644
|
||||||
|
--- a/login/Makefile
|
||||||
|
+++ b/login/Makefile
|
||||||
|
@@ -43,7 +43,8 @@ endif
|
||||||
|
subdir-dirs = programs
|
||||||
|
vpath %.c programs
|
||||||
|
|
||||||
|
-tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx
|
||||||
|
+tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
|
||||||
|
+ tst-pututxline-lockfail
|
||||||
|
|
||||||
|
# Build the -lutil library with these extra functions.
|
||||||
|
extra-libs := libutil
|
||||||
|
@@ -71,3 +72,5 @@ endif
|
||||||
|
$(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force)
|
||||||
|
$(make-target-directory)
|
||||||
|
-$(INSTALL_PROGRAM) -m 4755 -o root $< $@
|
||||||
|
+
|
||||||
|
+$(objpfx)tst-pututxline-lockfail: $(shared-thread-library)
|
||||||
|
diff --git a/login/tst-pututxline-lockfail.c b/login/tst-pututxline-lockfail.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..47c25dc0658d3c60
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/login/tst-pututxline-lockfail.c
|
||||||
|
@@ -0,0 +1,176 @@
|
||||||
|
+/* Test the lock upgrade path in tst-pututxline.
|
||||||
|
+ Copyright (C) 2019 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; see the file COPYING.LIB. If
|
||||||
|
+ not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* pututxline upgrades the read lock on the file to a write lock.
|
||||||
|
+ This test verifies that if the lock upgrade fails, the utmp
|
||||||
|
+ subsystem remains in a consistent state, so that pututxline can be
|
||||||
|
+ called again. */
|
||||||
|
+
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/namespace.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/temp_file.h>
|
||||||
|
+#include <support/xthread.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <utmp.h>
|
||||||
|
+#include <utmpx.h>
|
||||||
|
+
|
||||||
|
+/* Path to the temporary utmp file. */
|
||||||
|
+static char *path;
|
||||||
|
+
|
||||||
|
+/* Used to synchronize the subprocesses. The barrier itself is
|
||||||
|
+ allocated in shared memory. */
|
||||||
|
+static pthread_barrier_t *barrier;
|
||||||
|
+
|
||||||
|
+/* Use pututxline to write an entry for PID. */
|
||||||
|
+static struct utmpx *
|
||||||
|
+write_entry (pid_t pid)
|
||||||
|
+{
|
||||||
|
+ struct utmpx ut =
|
||||||
|
+ {
|
||||||
|
+ .ut_type = LOGIN_PROCESS,
|
||||||
|
+ .ut_id = "1",
|
||||||
|
+ .ut_user = "root",
|
||||||
|
+ .ut_pid = pid,
|
||||||
|
+ .ut_line = "entry",
|
||||||
|
+ .ut_host = "localhost",
|
||||||
|
+ };
|
||||||
|
+ return pututxline (&ut);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Create the initial entry in a subprocess, so that the utmp
|
||||||
|
+ subsystem in the original process is not disturbed. */
|
||||||
|
+static void
|
||||||
|
+subprocess_create_entry (void *closure)
|
||||||
|
+{
|
||||||
|
+ TEST_COMPARE (utmpname (path), 0);
|
||||||
|
+ TEST_VERIFY (write_entry (101) != NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Acquire an advisory read lock on PATH. */
|
||||||
|
+__attribute__ ((noreturn)) static void
|
||||||
|
+subprocess_lock_file (void)
|
||||||
|
+{
|
||||||
|
+ int fd = xopen (path, O_RDONLY, 0);
|
||||||
|
+
|
||||||
|
+ struct flock64 fl =
|
||||||
|
+ {
|
||||||
|
+ .l_type = F_RDLCK,
|
||||||
|
+ fl.l_whence = SEEK_SET,
|
||||||
|
+ };
|
||||||
|
+ TEST_COMPARE (fcntl64 (fd, F_SETLKW, &fl), 0);
|
||||||
|
+
|
||||||
|
+ /* Signal to the main process that the lock has been acquired. */
|
||||||
|
+ xpthread_barrier_wait (barrier);
|
||||||
|
+
|
||||||
|
+ /* Wait for the unlock request from the main process. */
|
||||||
|
+ xpthread_barrier_wait (barrier);
|
||||||
|
+
|
||||||
|
+ /* Implicitly unlock the file. */
|
||||||
|
+ xclose (fd);
|
||||||
|
+
|
||||||
|
+ /* Overwrite the existing entry. */
|
||||||
|
+ TEST_COMPARE (utmpname (path), 0);
|
||||||
|
+ errno = 0;
|
||||||
|
+ setutxent ();
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+ TEST_VERIFY (write_entry (102) != NULL);
|
||||||
|
+ errno = 0;
|
||||||
|
+ endutxent ();
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+
|
||||||
|
+ _exit (0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ xclose (create_temp_file ("tst-pututxline-lockfail-", &path));
|
||||||
|
+
|
||||||
|
+ {
|
||||||
|
+ pthread_barrierattr_t attr;
|
||||||
|
+ xpthread_barrierattr_init (&attr);
|
||||||
|
+ xpthread_barrierattr_setpshared (&attr, PTHREAD_SCOPE_PROCESS);
|
||||||
|
+ barrier = support_shared_allocate (sizeof (*barrier));
|
||||||
|
+ xpthread_barrier_init (barrier, &attr, 2);
|
||||||
|
+ xpthread_barrierattr_destroy (&attr);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Write the initial entry. */
|
||||||
|
+ support_isolate_in_subprocess (subprocess_create_entry, NULL);
|
||||||
|
+
|
||||||
|
+ pid_t locker_pid = xfork ();
|
||||||
|
+ if (locker_pid == 0)
|
||||||
|
+ subprocess_lock_file ();
|
||||||
|
+
|
||||||
|
+ /* Wait for the file locking to complete. */
|
||||||
|
+ xpthread_barrier_wait (barrier);
|
||||||
|
+
|
||||||
|
+ /* Try to add another entry. This attempt will fail, with EINTR or
|
||||||
|
+ EAGAIN. */
|
||||||
|
+ TEST_COMPARE (utmpname (path), 0);
|
||||||
|
+ TEST_VERIFY (write_entry (102) == NULL);
|
||||||
|
+ if (errno != EINTR)
|
||||||
|
+ TEST_COMPARE (errno, EAGAIN);
|
||||||
|
+
|
||||||
|
+ /* Signal the subprocess to overwrite the entry. */
|
||||||
|
+ xpthread_barrier_wait (barrier);
|
||||||
|
+
|
||||||
|
+ /* Wait for write and unlock to complete. */
|
||||||
|
+ {
|
||||||
|
+ int status;
|
||||||
|
+ xwaitpid (locker_pid, &status, 0);
|
||||||
|
+ TEST_COMPARE (status, 0);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* The file is no longer locked, so this operation will succeed. */
|
||||||
|
+ TEST_VERIFY (write_entry (103) != NULL);
|
||||||
|
+ errno = 0;
|
||||||
|
+ endutxent ();
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+
|
||||||
|
+ /* Check that there is just one entry with the expected contents.
|
||||||
|
+ If pututxline becomes desynchronized internally, the entry is not
|
||||||
|
+ overwritten (bug 24902). */
|
||||||
|
+ errno = 0;
|
||||||
|
+ setutxent ();
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+ struct utmpx *ut = getutxent ();
|
||||||
|
+ TEST_VERIFY_EXIT (ut != NULL);
|
||||||
|
+ TEST_COMPARE (ut->ut_type, LOGIN_PROCESS);
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_id, "1");
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_user, "root");
|
||||||
|
+ TEST_COMPARE (ut->ut_pid, 103);
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_line, "entry");
|
||||||
|
+ TEST_COMPARE_STRING (ut->ut_host, "localhost");
|
||||||
|
+ TEST_VERIFY (getutxent () == NULL);
|
||||||
|
+ errno = 0;
|
||||||
|
+ endutxent ();
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+
|
||||||
|
+ xpthread_barrier_destroy (barrier);
|
||||||
|
+ support_shared_free (barrier);
|
||||||
|
+ free (path);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index a736d3d25e005920..cbc53d06de280af9 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -185,9 +185,11 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+/* Search for *ID, updating last_entry and file_offset. Return 0 on
|
||||||
|
+ success and -1 on failure. If the locking operation failed, write
|
||||||
|
+ true to *LOCK_FAILED. */
|
||||||
|
static int
|
||||||
|
-internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
- bool *lock_failed)
|
||||||
|
+internal_getut_r (const struct utmp *id, bool *lock_failed)
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
@@ -206,7 +208,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* Read the next entry. */
|
||||||
|
- if (__read_nocancel (file_fd, buffer, sizeof (struct utmp))
|
||||||
|
+ if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp))
|
||||||
|
!= sizeof (struct utmp))
|
||||||
|
{
|
||||||
|
__set_errno (ESRCH);
|
||||||
|
@@ -215,7 +217,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
}
|
||||||
|
file_offset += sizeof (struct utmp);
|
||||||
|
|
||||||
|
- if (id->ut_type == buffer->ut_type)
|
||||||
|
+ if (id->ut_type == last_entry.ut_type)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -227,7 +229,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* Read the next entry. */
|
||||||
|
- if (__read_nocancel (file_fd, buffer, sizeof (struct utmp))
|
||||||
|
+ if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp))
|
||||||
|
!= sizeof (struct utmp))
|
||||||
|
{
|
||||||
|
__set_errno (ESRCH);
|
||||||
|
@@ -236,7 +238,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
}
|
||||||
|
file_offset += sizeof (struct utmp);
|
||||||
|
|
||||||
|
- if (__utmp_equal (buffer, id))
|
||||||
|
+ if (__utmp_equal (&last_entry, id))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -265,7 +267,7 @@ __libc_getutid_r (const struct utmp *id, struct utmp *buffer,
|
||||||
|
/* We don't have to distinguish whether we can lock the file or
|
||||||
|
whether there is no entry. */
|
||||||
|
bool lock_failed = false;
|
||||||
|
- if (internal_getut_r (id, &last_entry, &lock_failed) < 0)
|
||||||
|
+ if (internal_getut_r (id, &lock_failed) < 0)
|
||||||
|
{
|
||||||
|
*result = NULL;
|
||||||
|
return -1;
|
||||||
|
@@ -330,10 +332,9 @@ unlock_return:
|
||||||
|
struct utmp *
|
||||||
|
__libc_pututline (const struct utmp *data)
|
||||||
|
{
|
||||||
|
- if (!maybe_setutent ())
|
||||||
|
+ if (!maybe_setutent () || file_offset == -1l)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
- struct utmp buffer;
|
||||||
|
struct utmp *pbuf;
|
||||||
|
int found;
|
||||||
|
|
||||||
|
@@ -369,7 +370,7 @@ __libc_pututline (const struct utmp *data)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool lock_failed = false;
|
||||||
|
- found = internal_getut_r (data, &buffer, &lock_failed);
|
||||||
|
+ found = internal_getut_r (data, &lock_failed);
|
||||||
|
|
||||||
|
if (__builtin_expect (lock_failed, false))
|
||||||
|
{
|
86
SOURCES/glibc-rh1749439-8.patch
Normal file
86
SOURCES/glibc-rh1749439-8.patch
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
commit c2adefbafcdd2519ff43eca6891c77cd7b29ab62
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Aug 15 16:09:43 2019 +0200
|
||||||
|
|
||||||
|
login: Add nonstring attributes to struct utmp, struct utmpx [BZ #24899]
|
||||||
|
|
||||||
|
Commit 7532837d7b03b3ca5b9a63d77a5bd81dd23f3d9c ("The
|
||||||
|
-Wstringop-truncation option new in GCC 8 detects common misuses")
|
||||||
|
added __attribute_nonstring__ to bits/utmp.h, but it did not update
|
||||||
|
the parallel bits/utmpx.h header. In struct utmp, the nonstring
|
||||||
|
attribute for ut_id was missing.
|
||||||
|
|
||||||
|
diff --git a/bits/utmp.h b/bits/utmp.h
|
||||||
|
index 3c02dd4f3fe4e99b..854b342164b785e0 100644
|
||||||
|
--- a/bits/utmp.h
|
||||||
|
+++ b/bits/utmp.h
|
||||||
|
@@ -61,7 +61,8 @@ struct utmp
|
||||||
|
pid_t ut_pid; /* Process ID of login process. */
|
||||||
|
char ut_line[UT_LINESIZE]
|
||||||
|
__attribute_nonstring__; /* Devicename. */
|
||||||
|
- char ut_id[4]; /* Inittab ID. */
|
||||||
|
+ char ut_id[4]
|
||||||
|
+ __attribute_nonstring__; /* Inittab ID. */
|
||||||
|
char ut_user[UT_NAMESIZE]
|
||||||
|
__attribute_nonstring__; /* Username. */
|
||||||
|
char ut_host[UT_HOSTSIZE]
|
||||||
|
diff --git a/sysdeps/gnu/bits/utmpx.h b/sysdeps/gnu/bits/utmpx.h
|
||||||
|
index 2a77efc607ae2ac0..71c743ebfcd41194 100644
|
||||||
|
--- a/sysdeps/gnu/bits/utmpx.h
|
||||||
|
+++ b/sysdeps/gnu/bits/utmpx.h
|
||||||
|
@@ -56,10 +56,14 @@ struct utmpx
|
||||||
|
{
|
||||||
|
short int ut_type; /* Type of login. */
|
||||||
|
__pid_t ut_pid; /* Process ID of login process. */
|
||||||
|
- char ut_line[__UT_LINESIZE]; /* Devicename. */
|
||||||
|
- char ut_id[4]; /* Inittab ID. */
|
||||||
|
- char ut_user[__UT_NAMESIZE]; /* Username. */
|
||||||
|
- char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */
|
||||||
|
+ char ut_line[__UT_LINESIZE]
|
||||||
|
+ __attribute_nonstring__; /* Devicename. */
|
||||||
|
+ char ut_id[4]
|
||||||
|
+ __attribute_nonstring__; /* Inittab ID. */
|
||||||
|
+ char ut_user[__UT_NAMESIZE]
|
||||||
|
+ __attribute_nonstring__; /* Username. */
|
||||||
|
+ char ut_host[__UT_HOSTSIZE]
|
||||||
|
+ __attribute_nonstring__; /* Hostname for remote login. */
|
||||||
|
struct __exit_status ut_exit; /* Exit status of a process marked
|
||||||
|
as DEAD_PROCESS. */
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/s390/bits/utmp.h b/sysdeps/unix/sysv/linux/s390/bits/utmp.h
|
||||||
|
index b3fa362f478ae6fe..82e8d17e2e8cc031 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/s390/bits/utmp.h
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/s390/bits/utmp.h
|
||||||
|
@@ -61,7 +61,8 @@ struct utmp
|
||||||
|
pid_t ut_pid; /* Process ID of login process. */
|
||||||
|
char ut_line[UT_LINESIZE]
|
||||||
|
__attribute_nonstring__; /* Devicename. */
|
||||||
|
- char ut_id[4]; /* Inittab ID. */
|
||||||
|
+ char ut_id[4]
|
||||||
|
+ __attribute_nonstring__; /* Inittab ID. */
|
||||||
|
char ut_user[UT_NAMESIZE]
|
||||||
|
__attribute_nonstring__; /* Username. */
|
||||||
|
char ut_host[UT_HOSTSIZE]
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/s390/bits/utmpx.h b/sysdeps/unix/sysv/linux/s390/bits/utmpx.h
|
||||||
|
index 3d3036c3b91e6f57..3818ed3aa4df1e65 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/s390/bits/utmpx.h
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/s390/bits/utmpx.h
|
||||||
|
@@ -56,10 +56,14 @@ struct utmpx
|
||||||
|
{
|
||||||
|
short int ut_type; /* Type of login. */
|
||||||
|
__pid_t ut_pid; /* Process ID of login process. */
|
||||||
|
- char ut_line[__UT_LINESIZE]; /* Devicename. */
|
||||||
|
- char ut_id[4]; /* Inittab ID. */
|
||||||
|
- char ut_user[__UT_NAMESIZE]; /* Username. */
|
||||||
|
- char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */
|
||||||
|
+ char ut_line[__UT_LINESIZE]
|
||||||
|
+ __attribute_nonstring__; /* Devicename. */
|
||||||
|
+ char ut_id[4]
|
||||||
|
+ __attribute_nonstring__; /* Inittab ID. */
|
||||||
|
+ char ut_user[__UT_NAMESIZE]
|
||||||
|
+ __attribute_nonstring__; /* Username. */
|
||||||
|
+ char ut_host[__UT_HOSTSIZE]
|
||||||
|
+ __attribute_nonstring__; /* Hostname for remote login. */
|
||||||
|
struct __exit_status ut_exit; /* Exit status of a process marked
|
||||||
|
as DEAD_PROCESS. */
|
||||||
|
|
26
SOURCES/glibc-rh1749439-9.patch
Normal file
26
SOURCES/glibc-rh1749439-9.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
commit b0a83ae71b2588bd2a9e6b40f95191602940e01e
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Nov 7 09:53:41 2019 +0100
|
||||||
|
|
||||||
|
login: Remove double-assignment of fl.l_whence in try_file_lock
|
||||||
|
|
||||||
|
Since l_whence is the second member of struct flock, it is written
|
||||||
|
twice. The double-assignment is technically undefined behavior due to
|
||||||
|
the lack of a sequence point.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Change-Id: I2baf9e70690e723c61051b25ccbd510aec15976c
|
||||||
|
|
||||||
|
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
||||||
|
index cbc53d06de280af9..9ad80364682bae92 100644
|
||||||
|
--- a/login/utmp_file.c
|
||||||
|
+++ b/login/utmp_file.c
|
||||||
|
@@ -79,7 +79,7 @@ try_file_lock (int fd, int type)
|
||||||
|
struct flock64 fl =
|
||||||
|
{
|
||||||
|
.l_type = type,
|
||||||
|
- fl.l_whence = SEEK_SET,
|
||||||
|
+ .l_whence = SEEK_SET,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool status = __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0;
|
305
SOURCES/glibc-rh1764214.patch
Normal file
305
SOURCES/glibc-rh1764214.patch
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
commit bc79db3fd487daea36e7c130f943cfb9826a41b4
|
||||||
|
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||||
|
Date: Wed Feb 6 09:06:34 2019 +0100
|
||||||
|
|
||||||
|
Fix alignment of TLS variables for tls variant TLS_TCB_AT_TP [BZ #23403]
|
||||||
|
|
||||||
|
The alignment of TLS variables is wrong if accessed from within a thread
|
||||||
|
for architectures with tls variant TLS_TCB_AT_TP.
|
||||||
|
For the main thread the static tls data is properly aligned.
|
||||||
|
For other threads the alignment depends on the alignment of the thread
|
||||||
|
pointer as the static tls data is located relative to this pointer.
|
||||||
|
|
||||||
|
This patch adds this alignment for TLS_TCB_AT_TP variants in the same way
|
||||||
|
as it is already done for TLS_DTV_AT_TP. The thread pointer is also already
|
||||||
|
properly aligned if the user provides its own stack for the new thread.
|
||||||
|
|
||||||
|
This patch extends the testcase nptl/tst-tls1.c in order to check the
|
||||||
|
alignment of the tls variables and it adds a pthread_create invocation
|
||||||
|
with a user provided stack.
|
||||||
|
The test itself is migrated from test-skeleton.c to test-driver.c
|
||||||
|
and the missing support functions xpthread_attr_setstack and xposix_memalign
|
||||||
|
are added.
|
||||||
|
|
||||||
|
ChangeLog:
|
||||||
|
|
||||||
|
[BZ #23403]
|
||||||
|
* nptl/allocatestack.c (allocate_stack): Align pointer pd for
|
||||||
|
TLS_TCB_AT_TP tls variant.
|
||||||
|
* nptl/tst-tls1.c: Migrate to support/test-driver.c.
|
||||||
|
Add alignment checks.
|
||||||
|
* support/Makefile (libsupport-routines): Add xposix_memalign and
|
||||||
|
xpthread_setstack.
|
||||||
|
* support/support.h: Add xposix_memalign.
|
||||||
|
* support/xthread.h: Add xpthread_attr_setstack.
|
||||||
|
* support/xposix_memalign.c: New File.
|
||||||
|
* support/xpthread_attr_setstack.c: Likewise.
|
||||||
|
|
||||||
|
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
|
||||||
|
index 670cb8ffe6..590350647b 100644
|
||||||
|
--- a/nptl/allocatestack.c
|
||||||
|
+++ b/nptl/allocatestack.c
|
||||||
|
@@ -572,7 +572,9 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||||
|
|
||||||
|
/* Place the thread descriptor at the end of the stack. */
|
||||||
|
#if TLS_TCB_AT_TP
|
||||||
|
- pd = (struct pthread *) ((char *) mem + size) - 1;
|
||||||
|
+ pd = (struct pthread *) ((((uintptr_t) mem + size)
|
||||||
|
+ - TLS_TCB_SIZE)
|
||||||
|
+ & ~__static_tls_align_m1);
|
||||||
|
#elif TLS_DTV_AT_TP
|
||||||
|
pd = (struct pthread *) ((((uintptr_t) mem + size
|
||||||
|
- __static_tls_size)
|
||||||
|
diff --git a/nptl/tst-tls1.c b/nptl/tst-tls1.c
|
||||||
|
index 00489e23e9..1a915224a7 100644
|
||||||
|
--- a/nptl/tst-tls1.c
|
||||||
|
+++ b/nptl/tst-tls1.c
|
||||||
|
@@ -19,12 +19,16 @@
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
-
|
||||||
|
+#include <stdint.h>
|
||||||
|
+#include <inttypes.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xthread.h>
|
||||||
|
|
||||||
|
struct test_s
|
||||||
|
{
|
||||||
|
- int a;
|
||||||
|
- int b;
|
||||||
|
+ __attribute__ ((aligned(0x20))) int a;
|
||||||
|
+ __attribute__ ((aligned(0x200))) int b;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define INIT_A 1
|
||||||
|
@@ -36,15 +40,34 @@ __thread struct test_s s __attribute__ ((tls_model ("initial-exec"))) =
|
||||||
|
.b = INIT_B
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* Use noinline in combination with not static to ensure that the
|
||||||
|
+ alignment check is really done. Otherwise it was optimized out! */
|
||||||
|
+__attribute__ ((noinline)) void
|
||||||
|
+check_alignment (const char *thr_name, const char *ptr_name,
|
||||||
|
+ int *ptr, int alignment)
|
||||||
|
+{
|
||||||
|
+ uintptr_t offset_aligment = ((uintptr_t) ptr) & (alignment - 1);
|
||||||
|
+ if (offset_aligment)
|
||||||
|
+ {
|
||||||
|
+ FAIL_EXIT1 ("%s (%p) is not 0x%x-byte aligned in %s thread\n",
|
||||||
|
+ ptr_name, ptr, alignment, thr_name);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+check_s (const char *thr_name)
|
||||||
|
+{
|
||||||
|
+ if (s.a != INIT_A || s.b != INIT_B)
|
||||||
|
+ FAIL_EXIT1 ("initial value of s in %s thread wrong\n", thr_name);
|
||||||
|
+
|
||||||
|
+ check_alignment (thr_name, "s.a", &s.a, 0x20);
|
||||||
|
+ check_alignment (thr_name, "s.b", &s.b, 0x200);
|
||||||
|
+}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
tf (void *arg)
|
||||||
|
{
|
||||||
|
- if (s.a != INIT_A || s.b != INIT_B)
|
||||||
|
- {
|
||||||
|
- puts ("initial value of s in child thread wrong");
|
||||||
|
- exit (1);
|
||||||
|
- }
|
||||||
|
+ check_s ("child");
|
||||||
|
|
||||||
|
++s.a;
|
||||||
|
|
||||||
|
@@ -55,25 +78,14 @@ tf (void *arg)
|
||||||
|
int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
- if (s.a != INIT_A || s.b != INIT_B)
|
||||||
|
- {
|
||||||
|
- puts ("initial value of s in main thread wrong");
|
||||||
|
- exit (1);
|
||||||
|
- }
|
||||||
|
+ check_s ("main");
|
||||||
|
|
||||||
|
pthread_attr_t a;
|
||||||
|
|
||||||
|
- if (pthread_attr_init (&a) != 0)
|
||||||
|
- {
|
||||||
|
- puts ("attr_init failed");
|
||||||
|
- exit (1);
|
||||||
|
- }
|
||||||
|
+ xpthread_attr_init (&a);
|
||||||
|
|
||||||
|
- if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
|
||||||
|
- {
|
||||||
|
- puts ("attr_setstacksize failed");
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
+#define STACK_SIZE (1 * 1024 * 1024)
|
||||||
|
+ xpthread_attr_setstacksize (&a, STACK_SIZE);
|
||||||
|
|
||||||
|
#define N 10
|
||||||
|
int i;
|
||||||
|
@@ -83,29 +95,25 @@ do_test (void)
|
||||||
|
pthread_t th[M];
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < M; ++j, ++s.a)
|
||||||
|
- if (pthread_create (&th[j], &a, tf, NULL) != 0)
|
||||||
|
- {
|
||||||
|
- puts ("pthread_create failed");
|
||||||
|
- exit (1);
|
||||||
|
- }
|
||||||
|
+ th[j] = xpthread_create (&a, tf, NULL);
|
||||||
|
|
||||||
|
for (j = 0; j < M; ++j)
|
||||||
|
- if (pthread_join (th[j], NULL) != 0)
|
||||||
|
- {
|
||||||
|
- puts ("pthread_join failed");
|
||||||
|
- exit (1);
|
||||||
|
- }
|
||||||
|
+ xpthread_join (th[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (pthread_attr_destroy (&a) != 0)
|
||||||
|
- {
|
||||||
|
- puts ("attr_destroy failed");
|
||||||
|
- exit (1);
|
||||||
|
- }
|
||||||
|
+ /* Also check the alignment of the tls variables if a misaligned stack is
|
||||||
|
+ specified. */
|
||||||
|
+ pthread_t th;
|
||||||
|
+ void *thr_stack = NULL;
|
||||||
|
+ thr_stack = xposix_memalign (0x200, STACK_SIZE + 1);
|
||||||
|
+ xpthread_attr_setstack (&a, thr_stack + 1, STACK_SIZE);
|
||||||
|
+ th = xpthread_create (&a, tf, NULL);
|
||||||
|
+ xpthread_join (th);
|
||||||
|
+ free (thr_stack);
|
||||||
|
+
|
||||||
|
+ xpthread_attr_destroy (&a);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
-#define TEST_FUNCTION do_test ()
|
||||||
|
-#include "../test-skeleton.c"
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index c15b93647c..9ff0ec3fff 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -99,10 +99,12 @@ libsupport-routines = \
|
||||||
|
xopen \
|
||||||
|
xpipe \
|
||||||
|
xpoll \
|
||||||
|
+ xposix_memalign \
|
||||||
|
xpthread_attr_destroy \
|
||||||
|
xpthread_attr_init \
|
||||||
|
xpthread_attr_setdetachstate \
|
||||||
|
xpthread_attr_setguardsize \
|
||||||
|
+ xpthread_attr_setstack \
|
||||||
|
xpthread_attr_setstacksize \
|
||||||
|
xpthread_barrier_destroy \
|
||||||
|
xpthread_barrier_init \
|
||||||
|
diff --git a/support/support.h b/support/support.h
|
||||||
|
index 119495e5a9..97fef2cd23 100644
|
||||||
|
--- a/support/support.h
|
||||||
|
+++ b/support/support.h
|
||||||
|
@@ -86,6 +86,7 @@ int support_descriptor_supports_holes (int fd);
|
||||||
|
void *xmalloc (size_t) __attribute__ ((malloc));
|
||||||
|
void *xcalloc (size_t n, size_t s) __attribute__ ((malloc));
|
||||||
|
void *xrealloc (void *p, size_t n);
|
||||||
|
+void *xposix_memalign (size_t alignment, size_t n);
|
||||||
|
char *xasprintf (const char *format, ...)
|
||||||
|
__attribute__ ((format (printf, 1, 2), malloc));
|
||||||
|
char *xstrdup (const char *);
|
||||||
|
diff --git a/support/xposix_memalign.c b/support/xposix_memalign.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..5501a0846a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/xposix_memalign.c
|
||||||
|
@@ -0,0 +1,35 @@
|
||||||
|
+/* Error-checking wrapper for posix_memalign.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+
|
||||||
|
+void *
|
||||||
|
+xposix_memalign (size_t alignment, size_t n)
|
||||||
|
+{
|
||||||
|
+ void *p = NULL;
|
||||||
|
+
|
||||||
|
+ int ret = posix_memalign (&p, alignment, n);
|
||||||
|
+ if (ret)
|
||||||
|
+ {
|
||||||
|
+ errno = ret;
|
||||||
|
+ oom_error ("posix_memalign", n);
|
||||||
|
+ }
|
||||||
|
+ return p;
|
||||||
|
+}
|
||||||
|
diff --git a/support/xpthread_attr_setstack.c b/support/xpthread_attr_setstack.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..c3772e240b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/xpthread_attr_setstack.c
|
||||||
|
@@ -0,0 +1,26 @@
|
||||||
|
+/* pthread_attr_setstack with error checking.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <support/xthread.h>
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+xpthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, size_t stacksize)
|
||||||
|
+{
|
||||||
|
+ xpthread_check_return ("pthread_attr_setstack",
|
||||||
|
+ pthread_attr_setstack (attr, stackaddr, stacksize));
|
||||||
|
+}
|
||||||
|
diff --git a/support/xthread.h b/support/xthread.h
|
||||||
|
index 9fe1f68b3b..5204f78ed2 100644
|
||||||
|
--- a/support/xthread.h
|
||||||
|
+++ b/support/xthread.h
|
||||||
|
@@ -68,6 +68,8 @@ void xpthread_attr_destroy (pthread_attr_t *attr);
|
||||||
|
void xpthread_attr_init (pthread_attr_t *attr);
|
||||||
|
void xpthread_attr_setdetachstate (pthread_attr_t *attr,
|
||||||
|
int detachstate);
|
||||||
|
+void xpthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
|
||||||
|
+ size_t stacksize);
|
||||||
|
void xpthread_attr_setstacksize (pthread_attr_t *attr,
|
||||||
|
size_t stacksize);
|
||||||
|
void xpthread_attr_setguardsize (pthread_attr_t *attr,
|
192
SOURCES/glibc-rh1764218-1.patch
Normal file
192
SOURCES/glibc-rh1764218-1.patch
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
commit cb89ba9c72f66327f5d66034681eb1d46eedf96f
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Thu Aug 8 19:09:43 2019 -0400
|
||||||
|
|
||||||
|
Add glibc.malloc.mxfast tunable
|
||||||
|
|
||||||
|
* elf/dl-tunables.list: Add glibc.malloc.mxfast.
|
||||||
|
* manual/tunables.texi: Document it.
|
||||||
|
* malloc/malloc.c (do_set_mxfast): New.
|
||||||
|
(__libc_mallopt): Call it.
|
||||||
|
* malloc/arena.c: Add mxfast tunable.
|
||||||
|
* malloc/tst-mxfast.c: New.
|
||||||
|
* malloc/Makefile: Add it.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
(cherry picked from commit c48d92b430c480de06762f80c104922239416826)
|
||||||
|
|
||||||
|
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
|
||||||
|
index 1f8ecb8437a0460f..1ff6fcb6f24f93a8 100644
|
||||||
|
--- a/elf/dl-tunables.list
|
||||||
|
+++ b/elf/dl-tunables.list
|
||||||
|
@@ -85,6 +85,11 @@ glibc {
|
||||||
|
tcache_unsorted_limit {
|
||||||
|
type: SIZE_T
|
||||||
|
}
|
||||||
|
+ mxfast {
|
||||||
|
+ type: SIZE_T
|
||||||
|
+ minval: 0
|
||||||
|
+ security_level: SXID_IGNORE
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
tune {
|
||||||
|
hwcap_mask {
|
||||||
|
diff --git a/malloc/Makefile b/malloc/Makefile
|
||||||
|
index 228a1279a5960d8c..bf9a53cb7c5ebacb 100644
|
||||||
|
--- a/malloc/Makefile
|
||||||
|
+++ b/malloc/Makefile
|
||||||
|
@@ -39,6 +39,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
||||||
|
tst-malloc-too-large \
|
||||||
|
tst-malloc-stats-cancellation \
|
||||||
|
tst-tcfree1 tst-tcfree2 tst-tcfree3 \
|
||||||
|
+ tst-mxfast \
|
||||||
|
|
||||||
|
tests-static := \
|
||||||
|
tst-interpose-static-nothread \
|
||||||
|
@@ -196,6 +197,8 @@ tst-malloc-usable-static-ENV = $(tst-malloc-usable-ENV)
|
||||||
|
tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3
|
||||||
|
tst-malloc-usable-static-tunables-ENV = $(tst-malloc-usable-tunables-ENV)
|
||||||
|
|
||||||
|
+tst-mxfast-ENV = GLIBC_TUNABLES=glibc.malloc.tcache_count=0:glibc.malloc.mxfast=0
|
||||||
|
+
|
||||||
|
ifeq ($(experimental-malloc),yes)
|
||||||
|
CPPFLAGS-malloc.c += -DUSE_TCACHE=1
|
||||||
|
else
|
||||||
|
diff --git a/malloc/arena.c b/malloc/arena.c
|
||||||
|
index ff8fd5d2a7e51ac8..f5c7ad4570ad6186 100644
|
||||||
|
--- a/malloc/arena.c
|
||||||
|
+++ b/malloc/arena.c
|
||||||
|
@@ -237,6 +237,7 @@ TUNABLE_CALLBACK_FNDECL (set_tcache_max, size_t)
|
||||||
|
TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t)
|
||||||
|
TUNABLE_CALLBACK_FNDECL (set_tcache_unsorted_limit, size_t)
|
||||||
|
#endif
|
||||||
|
+TUNABLE_CALLBACK_FNDECL (set_mxfast, size_t)
|
||||||
|
#else
|
||||||
|
/* Initialization routine. */
|
||||||
|
#include <string.h>
|
||||||
|
@@ -324,6 +325,7 @@ ptmalloc_init (void)
|
||||||
|
TUNABLE_GET (tcache_unsorted_limit, size_t,
|
||||||
|
TUNABLE_CALLBACK (set_tcache_unsorted_limit));
|
||||||
|
# endif
|
||||||
|
+ TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast));
|
||||||
|
#else
|
||||||
|
const char *s = NULL;
|
||||||
|
if (__glibc_likely (_environ != NULL))
|
||||||
|
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||||
|
index fcf480acdaea1b86..9756ed0a0d28c5f6 100644
|
||||||
|
--- a/malloc/malloc.c
|
||||||
|
+++ b/malloc/malloc.c
|
||||||
|
@@ -5142,6 +5142,19 @@ do_set_tcache_unsorted_limit (size_t value)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+static inline int
|
||||||
|
+__always_inline
|
||||||
|
+do_set_mxfast (size_t value)
|
||||||
|
+{
|
||||||
|
+ if (value >= 0 && value <= MAX_FAST_SIZE)
|
||||||
|
+ {
|
||||||
|
+ LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ());
|
||||||
|
+ set_max_fast (value);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
__libc_mallopt (int param_number, int value)
|
||||||
|
{
|
||||||
|
@@ -5161,13 +5174,7 @@ __libc_mallopt (int param_number, int value)
|
||||||
|
switch (param_number)
|
||||||
|
{
|
||||||
|
case M_MXFAST:
|
||||||
|
- if (value >= 0 && value <= MAX_FAST_SIZE)
|
||||||
|
- {
|
||||||
|
- LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ());
|
||||||
|
- set_max_fast (value);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- res = 0;
|
||||||
|
+ do_set_mxfast (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case M_TRIM_THRESHOLD:
|
||||||
|
diff --git a/malloc/tst-mxfast.c b/malloc/tst-mxfast.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..7a371d2f9d2f0005
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/malloc/tst-mxfast.c
|
||||||
|
@@ -0,0 +1,50 @@
|
||||||
|
+/* Test that glibc.malloc.mxfast tunable works.
|
||||||
|
+ Copyright (C) 2018, 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* This test verifies that setting the glibc.malloc.mxfast tunable to
|
||||||
|
+ zero results in free'd blocks being returned to the small bins, not
|
||||||
|
+ the fast bins. */
|
||||||
|
+
|
||||||
|
+#include <malloc.h>
|
||||||
|
+#include <assert.h>
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+do_test(void)
|
||||||
|
+{
|
||||||
|
+ struct mallinfo m;
|
||||||
|
+ char * volatile p1;
|
||||||
|
+ char * volatile p2;
|
||||||
|
+
|
||||||
|
+ /* Arbitrary value; must be in default fastbin range. */
|
||||||
|
+ p1 = malloc (3);
|
||||||
|
+ /* Something large so that p1 isn't a "top block" */
|
||||||
|
+ p2 = malloc (512);
|
||||||
|
+ free (p1);
|
||||||
|
+
|
||||||
|
+ m = mallinfo();
|
||||||
|
+
|
||||||
|
+ /* This will fail if there are any blocks in the fastbins. */
|
||||||
|
+ assert (m.smblks == 0);
|
||||||
|
+
|
||||||
|
+ /* To keep gcc happy. */
|
||||||
|
+ free (p2);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/manual/tunables.texi b/manual/tunables.texi
|
||||||
|
index f6c49250e3889ddd..3dc6f9a44592c030 100644
|
||||||
|
--- a/manual/tunables.texi
|
||||||
|
+++ b/manual/tunables.texi
|
||||||
|
@@ -213,6 +213,18 @@ pre-fill the per-thread cache with. The default, or when set to zero,
|
||||||
|
is no limit.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
+@deftp Tunable glibc.malloc.mxfast
|
||||||
|
+One of the optimizations malloc uses is to maintain a series of ``fast
|
||||||
|
+bins'' that hold chunks up to a specific size. The default and
|
||||||
|
+maximum size which may be held this way is 80 bytes on 32-bit systems
|
||||||
|
+or 160 bytes on 64-bit systems. Applications which value size over
|
||||||
|
+speed may choose to reduce the size of requests which are serviced
|
||||||
|
+from fast bins with this tunable. Note that the value specified
|
||||||
|
+includes malloc's internal overhead, which is normally the size of one
|
||||||
|
+pointer, so add 4 on 32-bit systems or 8 on 64-bit systems to the size
|
||||||
|
+passed to @code{malloc} for the largest bin size to enable.
|
||||||
|
+@end deftp
|
||||||
|
+
|
||||||
|
@node Elision Tunables
|
||||||
|
@section Elision Tunables
|
||||||
|
@cindex elision tunables
|
72
SOURCES/glibc-rh1764218-2.patch
Normal file
72
SOURCES/glibc-rh1764218-2.patch
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
commit 5dab5eafb3dc2f72aaab911084d127d1af45a08c
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Aug 15 11:37:18 2019 +0200
|
||||||
|
|
||||||
|
malloc: Various cleanups for malloc/tst-mxfast
|
||||||
|
|
||||||
|
(cherry picked from commit f9769a239784772453d595bc2f4bed8739810e06)
|
||||||
|
|
||||||
|
diff --git a/malloc/Makefile b/malloc/Makefile
|
||||||
|
index bf9a53cb7c5ebacb..19c2a846ed8ce049 100644
|
||||||
|
--- a/malloc/Makefile
|
||||||
|
+++ b/malloc/Makefile
|
||||||
|
@@ -39,7 +39,6 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
||||||
|
tst-malloc-too-large \
|
||||||
|
tst-malloc-stats-cancellation \
|
||||||
|
tst-tcfree1 tst-tcfree2 tst-tcfree3 \
|
||||||
|
- tst-mxfast \
|
||||||
|
|
||||||
|
tests-static := \
|
||||||
|
tst-interpose-static-nothread \
|
||||||
|
@@ -55,7 +54,7 @@ tests-internal += \
|
||||||
|
tst-dynarray-at-fail \
|
||||||
|
|
||||||
|
ifneq (no,$(have-tunables))
|
||||||
|
-tests += tst-malloc-usable-tunables
|
||||||
|
+tests += tst-malloc-usable-tunables tst-mxfast
|
||||||
|
tests-static += tst-malloc-usable-static-tunables
|
||||||
|
endif
|
||||||
|
|
||||||
|
diff --git a/malloc/tst-mxfast.c b/malloc/tst-mxfast.c
|
||||||
|
index 7a371d2f9d2f0005..7a7750bc71024bfb 100644
|
||||||
|
--- a/malloc/tst-mxfast.c
|
||||||
|
+++ b/malloc/tst-mxfast.c
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
/* Test that glibc.malloc.mxfast tunable works.
|
||||||
|
- Copyright (C) 2018, 2019 Free Software Foundation, Inc.
|
||||||
|
+ Copyright (C) 2019 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
|
||||||
|
@@ -21,14 +21,14 @@
|
||||||
|
the fast bins. */
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
-#include <assert.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
-do_test(void)
|
||||||
|
+do_test (void)
|
||||||
|
{
|
||||||
|
struct mallinfo m;
|
||||||
|
- char * volatile p1;
|
||||||
|
- char * volatile p2;
|
||||||
|
+ char *volatile p1;
|
||||||
|
+ char *volatile p2;
|
||||||
|
|
||||||
|
/* Arbitrary value; must be in default fastbin range. */
|
||||||
|
p1 = malloc (3);
|
||||||
|
@@ -36,10 +36,10 @@ do_test(void)
|
||||||
|
p2 = malloc (512);
|
||||||
|
free (p1);
|
||||||
|
|
||||||
|
- m = mallinfo();
|
||||||
|
+ m = mallinfo ();
|
||||||
|
|
||||||
|
/* This will fail if there are any blocks in the fastbins. */
|
||||||
|
- assert (m.smblks == 0);
|
||||||
|
+ TEST_COMPARE (m.smblks, 0);
|
||||||
|
|
||||||
|
/* To keep gcc happy. */
|
||||||
|
free (p2);
|
31
SOURCES/glibc-rh1764218-3.patch
Normal file
31
SOURCES/glibc-rh1764218-3.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
commit f144981490bd2ab13189d85902ca74beecb307e4
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Wed Oct 30 18:03:14 2019 -0400
|
||||||
|
|
||||||
|
Base max_fast on alignment, not width, of bins (Bug 24903)
|
||||||
|
|
||||||
|
set_max_fast sets the "impossibly small" value based on,
|
||||||
|
eventually, MALLOC_ALIGNMENT. The comparisons for the smallest
|
||||||
|
chunk used is, eventually, MIN_CHUNK_SIZE. Note that i386
|
||||||
|
is the only platform where these are the same, so a smallest
|
||||||
|
chunk *would* be put in a no-fastbins fastbin.
|
||||||
|
|
||||||
|
This change calculates the "impossibly small" value
|
||||||
|
based on MIN_CHUNK_SIZE instead, so that we can know it will
|
||||||
|
always be impossibly small.
|
||||||
|
|
||||||
|
(cherry picked from commit ff12e0fb91b9072800f031cb21fb2651ee7b6251)
|
||||||
|
|
||||||
|
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||||
|
index 9756ed0a0d28c5f6..90825b2aaed53761 100644
|
||||||
|
--- a/malloc/malloc.c
|
||||||
|
+++ b/malloc/malloc.c
|
||||||
|
@@ -1635,7 +1635,7 @@ static INTERNAL_SIZE_T global_max_fast;
|
||||||
|
|
||||||
|
#define set_max_fast(s) \
|
||||||
|
global_max_fast = (((s) == 0) \
|
||||||
|
- ? SMALLBIN_WIDTH : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK))
|
||||||
|
+ ? MIN_CHUNK_SIZE / 2 : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK))
|
||||||
|
|
||||||
|
static inline INTERNAL_SIZE_T
|
||||||
|
get_max_fast (void)
|
142
SOURCES/glibc-rh1764223.patch
Normal file
142
SOURCES/glibc-rh1764223.patch
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
commit 2c75b545de6fe3c44138799c68217a94bc669a88
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Tue Jun 18 16:42:10 2019 +0200
|
||||||
|
|
||||||
|
elf: Refuse to dlopen PIE objects [BZ #24323]
|
||||||
|
|
||||||
|
Another executable has already been mapped, so the dynamic linker
|
||||||
|
cannot perform relocations correctly for the second executable.
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 08e2f99..27a2fa8 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -310,7 +310,7 @@ test-xfail-tst-protected1b = yes
|
||||||
|
endif
|
||||||
|
ifeq (yesyes,$(have-fpie)$(build-shared))
|
||||||
|
modules-names += tst-piemod1
|
||||||
|
-tests += tst-pie1 tst-pie2
|
||||||
|
+tests += tst-pie1 tst-pie2 tst-dlopen-pie
|
||||||
|
tests-pie += tst-pie1 tst-pie2
|
||||||
|
ifeq (yes,$(have-protected-data))
|
||||||
|
tests += vismain
|
||||||
|
@@ -1084,6 +1084,8 @@ CFLAGS-tst-pie2.c += $(pie-ccflag)
|
||||||
|
|
||||||
|
$(objpfx)tst-piemod1.so: $(libsupport)
|
||||||
|
$(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
|
||||||
|
+$(objpfx)tst-dlopen-pie: $(libdl)
|
||||||
|
+$(objpfx)tst-dlopen-pie.out: $(objpfx)tst-pie1
|
||||||
|
|
||||||
|
ifeq (yes,$(build-shared))
|
||||||
|
# NB: Please keep cet-built-dso in sysdeps/x86/Makefile in sync with
|
||||||
|
diff --git a/elf/dl-load.c b/elf/dl-load.c
|
||||||
|
index 2bbef81..5abeb86 100644
|
||||||
|
--- a/elf/dl-load.c
|
||||||
|
+++ b/elf/dl-load.c
|
||||||
|
@@ -1158,6 +1158,10 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||||
|
goto call_lose;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* dlopen of an executable is not valid because it is not possible
|
||||||
|
+ to perform proper relocations, handle static TLS, or run the
|
||||||
|
+ ELF constructors. For PIE, the check needs the dynamic
|
||||||
|
+ section, so there is another check below. */
|
||||||
|
if (__glibc_unlikely (type != ET_DYN)
|
||||||
|
&& __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0))
|
||||||
|
{
|
||||||
|
@@ -1194,9 +1198,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||||
|
elf_get_dynamic_info (l, NULL);
|
||||||
|
|
||||||
|
/* Make sure we are not dlopen'ing an object that has the
|
||||||
|
- DF_1_NOOPEN flag set. */
|
||||||
|
- if (__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN)
|
||||||
|
- && (mode & __RTLD_DLOPEN))
|
||||||
|
+ DF_1_NOOPEN flag set, or a PIE object. */
|
||||||
|
+ if ((__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN)
|
||||||
|
+ && (mode & __RTLD_DLOPEN))
|
||||||
|
+ || (__glibc_unlikely (l->l_flags_1 & DF_1_PIE)
|
||||||
|
+ && __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0)))
|
||||||
|
{
|
||||||
|
/* We are not supposed to load this object. Free all resources. */
|
||||||
|
_dl_unmap_segments (l);
|
||||||
|
@@ -1207,7 +1213,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||||
|
if (l->l_phdr_allocated)
|
||||||
|
free ((void *) l->l_phdr);
|
||||||
|
|
||||||
|
- errstring = N_("shared object cannot be dlopen()ed");
|
||||||
|
+ if (l->l_flags_1 & DF_1_PIE)
|
||||||
|
+ errstring
|
||||||
|
+ = N_("cannot dynamically load position-independent executable");
|
||||||
|
+ else
|
||||||
|
+ errstring = N_("shared object cannot be dlopen()ed");
|
||||||
|
goto call_lose;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/elf/tst-dlopen-pie.c b/elf/tst-dlopen-pie.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..6a41c73
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-dlopen-pie.c
|
||||||
|
@@ -0,0 +1,49 @@
|
||||||
|
+/* dlopen test for PIE objects.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* This test attempts to open the (otherwise unrelated) PIE test
|
||||||
|
+ program elf/tst-pie1 and expects the attempt to fail. */
|
||||||
|
+
|
||||||
|
+#include <dlfcn.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+test_mode (int mode)
|
||||||
|
+{
|
||||||
|
+ char *pie_path = xasprintf ("%s/elf/tst-pie1", support_objdir_root);
|
||||||
|
+ if (dlopen (pie_path, mode) != NULL)
|
||||||
|
+ FAIL_EXIT1 ("dlopen succeeded unexpectedly (%d)", mode);
|
||||||
|
+ const char *message = dlerror ();
|
||||||
|
+ const char *expected
|
||||||
|
+ = "cannot dynamically load position-independent executable";
|
||||||
|
+ if (strstr (message, expected) == NULL)
|
||||||
|
+ FAIL_EXIT1 ("unexpected error message (mode %d): %s", mode, message);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ test_mode (RTLD_LAZY);
|
||||||
|
+ test_mode (RTLD_NOW);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/include/elf.h b/include/elf.h
|
||||||
|
index ab76aaf..14ed67f 100644
|
||||||
|
--- a/include/elf.h
|
||||||
|
+++ b/include/elf.h
|
||||||
|
@@ -23,7 +23,7 @@
|
||||||
|
# endif
|
||||||
|
# define DT_1_SUPPORTED_MASK \
|
||||||
|
(DF_1_NOW | DF_1_NODELETE | DF_1_INITFIRST | DF_1_NOOPEN \
|
||||||
|
- | DF_1_ORIGIN | DF_1_NODEFLIB)
|
||||||
|
+ | DF_1_ORIGIN | DF_1_NODEFLIB | DF_1_PIE)
|
||||||
|
|
||||||
|
#endif /* !_ISOMAC */
|
||||||
|
#endif /* elf.h */
|
82
SOURCES/glibc-rh1764226-1.patch
Normal file
82
SOURCES/glibc-rh1764226-1.patch
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
commit 6c29942cbf059aca47fd4bbd852ea42c9d46b71f
|
||||||
|
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||||
|
Date: Mon Feb 18 16:12:01 2019 +0100
|
||||||
|
|
||||||
|
misc/tst-clone3: Fix waiting for exited thread.
|
||||||
|
|
||||||
|
From time to time the test misc/tst-clone3 fails with a timeout.
|
||||||
|
Then futex_wait is blocking. Usually ctid should be set to zero
|
||||||
|
due to CLONE_CHILD_CLEARTID and the futex should be waken up.
|
||||||
|
But the fail occures if the thread has already exited before
|
||||||
|
ctid is set to the return value of clone(). Then futex_wait() will
|
||||||
|
block as there will be nobody who wakes the futex up again.
|
||||||
|
|
||||||
|
This patch initializes ctid to a known value before calling clone
|
||||||
|
and the kernel is the only one who updates the value to zero after clone.
|
||||||
|
If futex_wait is called then it is either waked up due to the exited thread
|
||||||
|
or the futex syscall fails as *ctid_ptr is already zero instead of the
|
||||||
|
specified value 1.
|
||||||
|
|
||||||
|
ChangeLog:
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/tst-clone3.c (do_test):
|
||||||
|
Initialize ctid with a known value and remove update of ctid
|
||||||
|
after clone.
|
||||||
|
(wait_tid): Adjust arguments and call futex_wait with ctid_val
|
||||||
|
as assumed current value of ctid_ptr.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/tst-clone3.c b/sysdeps/unix/sysv/linux/tst-clone3.c
|
||||||
|
index 784ce18f5343ec72..9f1ed6355e7acffd 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/tst-clone3.c
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/tst-clone3.c
|
||||||
|
@@ -27,6 +27,7 @@
|
||||||
|
|
||||||
|
#include <stackinfo.h> /* For _STACK_GROWS_{UP,DOWN}. */
|
||||||
|
#include <support/check.h>
|
||||||
|
+#include <stdatomic.h>
|
||||||
|
|
||||||
|
/* Test if clone call with CLONE_THREAD does not call exit_group. The 'f'
|
||||||
|
function returns '1', which will be used by clone thread to call the
|
||||||
|
@@ -42,11 +43,14 @@ f (void *a)
|
||||||
|
|
||||||
|
/* Futex wait for TID argument, similar to pthread_join internal
|
||||||
|
implementation. */
|
||||||
|
-#define wait_tid(tid) \
|
||||||
|
- do { \
|
||||||
|
- __typeof (tid) __tid; \
|
||||||
|
- while ((__tid = (tid)) != 0) \
|
||||||
|
- futex_wait (&(tid), __tid); \
|
||||||
|
+#define wait_tid(ctid_ptr, ctid_val) \
|
||||||
|
+ do { \
|
||||||
|
+ __typeof (*(ctid_ptr)) __tid; \
|
||||||
|
+ /* We need acquire MO here so that we synchronize with the \
|
||||||
|
+ kernel's store to 0 when the clone terminates. */ \
|
||||||
|
+ while ((__tid = atomic_load_explicit (ctid_ptr, \
|
||||||
|
+ memory_order_acquire)) != 0) \
|
||||||
|
+ futex_wait (ctid_ptr, ctid_val); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
@@ -64,7 +68,11 @@ do_test (void)
|
||||||
|
clone_flags |= CLONE_VM | CLONE_SIGHAND;
|
||||||
|
/* We will used ctid to call on futex to wait for thread exit. */
|
||||||
|
clone_flags |= CLONE_CHILD_CLEARTID;
|
||||||
|
- pid_t ctid, tid;
|
||||||
|
+ /* Initialize with a known value. ctid is set to zero by the kernel after the
|
||||||
|
+ cloned thread has exited. */
|
||||||
|
+#define CTID_INIT_VAL 1
|
||||||
|
+ pid_t ctid = CTID_INIT_VAL;
|
||||||
|
+ pid_t tid;
|
||||||
|
|
||||||
|
#ifdef __ia64__
|
||||||
|
extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
|
||||||
|
@@ -86,8 +94,7 @@ do_test (void)
|
||||||
|
if (tid == -1)
|
||||||
|
FAIL_EXIT1 ("clone failed: %m");
|
||||||
|
|
||||||
|
- ctid = tid;
|
||||||
|
- wait_tid (ctid);
|
||||||
|
+ wait_tid (&ctid, CTID_INIT_VAL);
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
159
SOURCES/glibc-rh1764226-2.patch
Normal file
159
SOURCES/glibc-rh1764226-2.patch
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
commit 481c30cb9573a280649fbf27251e6a0f4af1b2b1
|
||||||
|
Author: Alexandra Hájková <ahajkova@redhat.com>
|
||||||
|
Date: Thu May 9 13:51:40 2019 +0200
|
||||||
|
|
||||||
|
elf: Add tst-ldconfig-bad-aux-cache test [BZ #18093]
|
||||||
|
|
||||||
|
This test corrupts /var/cache/ldconfig/aux-cache and executes ldconfig
|
||||||
|
to check it will not segfault using the corrupted aux_cache. The test
|
||||||
|
uses the test-in-container framework. Verified no regressions on
|
||||||
|
x86_64.
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 139d072e136284e1..8e907e69eb35e089 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -156,6 +156,9 @@ tests-static-internal := tst-tls1-static tst-tls2-static \
|
||||||
|
CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o
|
||||||
|
tst-tls1-static-non-pie-no-pie = yes
|
||||||
|
|
||||||
|
+tests-container = \
|
||||||
|
+ tst-ldconfig-bad-aux-cache
|
||||||
|
+
|
||||||
|
tests := tst-tls9 tst-leaks1 \
|
||||||
|
tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
|
||||||
|
tst-auxv
|
||||||
|
diff --git a/elf/tst-ldconfig-bad-aux-cache.c b/elf/tst-ldconfig-bad-aux-cache.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..68ce90a95648f6ab
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-ldconfig-bad-aux-cache.c
|
||||||
|
@@ -0,0 +1,117 @@
|
||||||
|
+/* Test ldconfig does not segfault when aux-cache is corrupted (Bug 18093).
|
||||||
|
+ Copyright (C) 2019 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; see the file COPYING.LIB. If
|
||||||
|
+ not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* This test does the following:
|
||||||
|
+ Run ldconfig to create the caches.
|
||||||
|
+ Corrupt the caches.
|
||||||
|
+ Run ldconfig again.
|
||||||
|
+ At each step we verify that ldconfig does not crash. */
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <sys/wait.h>
|
||||||
|
+#include <ftw.h>
|
||||||
|
+#include <stdint.h>
|
||||||
|
+
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+
|
||||||
|
+#include <dirent.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+display_info (const char *fpath, const struct stat *sb,
|
||||||
|
+ int tflag, struct FTW *ftwbuf)
|
||||||
|
+{
|
||||||
|
+ printf ("info: %-3s %2d %7jd %-40s %d %s\n",
|
||||||
|
+ (tflag == FTW_D) ? "d" : (tflag == FTW_DNR) ? "dnr" :
|
||||||
|
+ (tflag == FTW_DP) ? "dp" : (tflag == FTW_F) ? "f" :
|
||||||
|
+ (tflag == FTW_NS) ? "ns" : (tflag == FTW_SL) ? "sl" :
|
||||||
|
+ (tflag == FTW_SLN) ? "sln" : "???",
|
||||||
|
+ ftwbuf->level, (intmax_t) sb->st_size,
|
||||||
|
+ fpath, ftwbuf->base, fpath + ftwbuf->base);
|
||||||
|
+ /* To tell nftw to continue. */
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Run ldconfig with a corrupt aux-cache, in particular we test for size
|
||||||
|
+ truncation that might happen if a previous ldconfig run failed or if
|
||||||
|
+ there were storage or power issues while we were writing the file.
|
||||||
|
+ We want ldconfig not to crash, and it should be able to do so by
|
||||||
|
+ computing the expected size of the file (bug 18093). */
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ char *prog = xasprintf ("%s/ldconfig", support_install_rootsbindir);
|
||||||
|
+ char *const args[] = { prog, NULL };
|
||||||
|
+ const char *path = "/var/cache/ldconfig/aux-cache";
|
||||||
|
+ struct stat64 fs;
|
||||||
|
+ long int size, new_size, i;
|
||||||
|
+ int status;
|
||||||
|
+ pid_t pid;
|
||||||
|
+
|
||||||
|
+ /* Create the needed directories. */
|
||||||
|
+ xmkdirp ("/var/cache/ldconfig", 0777);
|
||||||
|
+
|
||||||
|
+ pid = xfork ();
|
||||||
|
+ /* Run ldconfig fist to generate the aux-cache. */
|
||||||
|
+ if (pid == 0)
|
||||||
|
+ {
|
||||||
|
+ execv (args[0], args);
|
||||||
|
+ _exit (1);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ xwaitpid (pid, &status, 0);
|
||||||
|
+ TEST_COMPARE(status, 0);
|
||||||
|
+ xstat (path, &fs);
|
||||||
|
+
|
||||||
|
+ size = fs.st_size;
|
||||||
|
+ /* Run 3 tests, each truncating aux-cache shorter and shorter. */
|
||||||
|
+ for (i = 3; i > 0; i--)
|
||||||
|
+ {
|
||||||
|
+ new_size = size * i / 4;
|
||||||
|
+ if (truncate (path, new_size))
|
||||||
|
+ FAIL_EXIT1 ("truncation failed: %m");
|
||||||
|
+ if (nftw (path, display_info, 1000, 0) == -1)
|
||||||
|
+ FAIL_EXIT1 ("nftw failed.");
|
||||||
|
+
|
||||||
|
+ pid = xfork ();
|
||||||
|
+ /* Verify that ldconfig can run with a truncated
|
||||||
|
+ aux-cache and doesn't crash. */
|
||||||
|
+ if (pid == 0)
|
||||||
|
+ {
|
||||||
|
+ execv (args[0], args);
|
||||||
|
+ _exit (1);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ xwaitpid (pid, &status, 0);
|
||||||
|
+ TEST_COMPARE(status, 0);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free (prog);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-ldconfig-bad-aux-cache.root/etc/ld.so.conf b/elf/tst-ldconfig-bad-aux-cache.root/etc/ld.so.conf
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..e1e74dbda2bf3dfa
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-ldconfig-bad-aux-cache.root/etc/ld.so.conf
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+# This file was created to suppress a warning from ldconfig:
|
||||||
|
+# /sbin/ldconfig: Warning: ignoring configuration file that cannot be opened: /etc/ld.so.conf: No such file or directory
|
||||||
|
diff --git a/elf/tst-ldconfig-bad-aux-cache.root/postclean.req b/elf/tst-ldconfig-bad-aux-cache.root/postclean.req
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..e69de29bb2d1d643
|
112
SOURCES/glibc-rh1764226-3.patch
Normal file
112
SOURCES/glibc-rh1764226-3.patch
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
commit a6c1ce778e5c05a2e6925883b410157ef47654fd
|
||||||
|
Author: Alexandra Hájková <ahajkova@redhat.com>
|
||||||
|
Date: Mon Aug 5 13:18:57 2019 +0200
|
||||||
|
|
||||||
|
elf: tst-ldconfig-bad-aux-cache: use support_capture_subprocess
|
||||||
|
|
||||||
|
diff --git a/elf/tst-ldconfig-bad-aux-cache.c b/elf/tst-ldconfig-bad-aux-cache.c
|
||||||
|
index 68ce90a95648f6ab..6e22ff815eaaa817 100644
|
||||||
|
--- a/elf/tst-ldconfig-bad-aux-cache.c
|
||||||
|
+++ b/elf/tst-ldconfig-bad-aux-cache.c
|
||||||
|
@@ -31,6 +31,7 @@
|
||||||
|
#include <ftw.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
+#include <support/capture_subprocess.h>
|
||||||
|
#include <support/check.h>
|
||||||
|
#include <support/support.h>
|
||||||
|
#include <support/xunistd.h>
|
||||||
|
@@ -52,6 +53,15 @@ display_info (const char *fpath, const struct stat *sb,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+execv_wrapper (void *args)
|
||||||
|
+{
|
||||||
|
+ char **argv = args;
|
||||||
|
+
|
||||||
|
+ execv (argv[0], argv);
|
||||||
|
+ FAIL_EXIT1 ("execv: %m");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Run ldconfig with a corrupt aux-cache, in particular we test for size
|
||||||
|
truncation that might happen if a previous ldconfig run failed or if
|
||||||
|
there were storage or power issues while we were writing the file.
|
||||||
|
@@ -61,53 +71,38 @@ static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
char *prog = xasprintf ("%s/ldconfig", support_install_rootsbindir);
|
||||||
|
- char *const args[] = { prog, NULL };
|
||||||
|
+ char *args[] = { prog, NULL };
|
||||||
|
const char *path = "/var/cache/ldconfig/aux-cache";
|
||||||
|
struct stat64 fs;
|
||||||
|
long int size, new_size, i;
|
||||||
|
- int status;
|
||||||
|
- pid_t pid;
|
||||||
|
|
||||||
|
/* Create the needed directories. */
|
||||||
|
xmkdirp ("/var/cache/ldconfig", 0777);
|
||||||
|
|
||||||
|
- pid = xfork ();
|
||||||
|
- /* Run ldconfig fist to generate the aux-cache. */
|
||||||
|
- if (pid == 0)
|
||||||
|
- {
|
||||||
|
- execv (args[0], args);
|
||||||
|
- _exit (1);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
+ /* Run ldconfig first to generate the aux-cache. */
|
||||||
|
+ struct support_capture_subprocess result;
|
||||||
|
+ result = support_capture_subprocess (execv_wrapper, args);
|
||||||
|
+ support_capture_subprocess_check (&result, "execv", 0, sc_allow_none);
|
||||||
|
+ support_capture_subprocess_free (&result);
|
||||||
|
+
|
||||||
|
+ xstat (path, &fs);
|
||||||
|
+
|
||||||
|
+ size = fs.st_size;
|
||||||
|
+ /* Run 3 tests, each truncating aux-cache shorter and shorter. */
|
||||||
|
+ for (i = 3; i > 0; i--)
|
||||||
|
{
|
||||||
|
- xwaitpid (pid, &status, 0);
|
||||||
|
- TEST_COMPARE(status, 0);
|
||||||
|
- xstat (path, &fs);
|
||||||
|
-
|
||||||
|
- size = fs.st_size;
|
||||||
|
- /* Run 3 tests, each truncating aux-cache shorter and shorter. */
|
||||||
|
- for (i = 3; i > 0; i--)
|
||||||
|
- {
|
||||||
|
- new_size = size * i / 4;
|
||||||
|
- if (truncate (path, new_size))
|
||||||
|
- FAIL_EXIT1 ("truncation failed: %m");
|
||||||
|
- if (nftw (path, display_info, 1000, 0) == -1)
|
||||||
|
- FAIL_EXIT1 ("nftw failed.");
|
||||||
|
-
|
||||||
|
- pid = xfork ();
|
||||||
|
- /* Verify that ldconfig can run with a truncated
|
||||||
|
- aux-cache and doesn't crash. */
|
||||||
|
- if (pid == 0)
|
||||||
|
- {
|
||||||
|
- execv (args[0], args);
|
||||||
|
- _exit (1);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- xwaitpid (pid, &status, 0);
|
||||||
|
- TEST_COMPARE(status, 0);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ new_size = size * i / 4;
|
||||||
|
+ if (truncate (path, new_size))
|
||||||
|
+ FAIL_EXIT1 ("truncation failed: %m");
|
||||||
|
+ if (nftw (path, display_info, 1000, 0) == -1)
|
||||||
|
+ FAIL_EXIT1 ("nftw failed.");
|
||||||
|
+
|
||||||
|
+ /* Verify that ldconfig can run with a truncated
|
||||||
|
+ aux-cache and doesn't crash. */
|
||||||
|
+ struct support_capture_subprocess result;
|
||||||
|
+ result = support_capture_subprocess (execv_wrapper, args);
|
||||||
|
+ support_capture_subprocess_check (&result, "execv", 0, sc_allow_none);
|
||||||
|
+ support_capture_subprocess_free (&result);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (prog);
|
49
SOURCES/glibc-rh1764231-1.patch
Normal file
49
SOURCES/glibc-rh1764231-1.patch
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
commit 17432d7150bdab3bce2ea66c70ad6c920f54077a
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Jun 28 10:15:30 2019 +0200
|
||||||
|
|
||||||
|
support: Add xdlvsym function
|
||||||
|
|
||||||
|
diff --git a/support/xdlfcn.c b/support/xdlfcn.c
|
||||||
|
index f34bb059c00f27f7..b4a6b85649d181c8 100644
|
||||||
|
--- a/support/xdlfcn.c
|
||||||
|
+++ b/support/xdlfcn.c
|
||||||
|
@@ -48,6 +48,26 @@ xdlsym (void *handle, const char *symbol)
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void *
|
||||||
|
+xdlvsym (void *handle, const char *symbol, const char *version)
|
||||||
|
+{
|
||||||
|
+ /* Clear any pending errors. */
|
||||||
|
+ dlerror ();
|
||||||
|
+
|
||||||
|
+ void *sym = dlvsym (handle, symbol, version);
|
||||||
|
+
|
||||||
|
+ if (sym == NULL)
|
||||||
|
+ {
|
||||||
|
+ const char *error = dlerror ();
|
||||||
|
+ if (error != NULL)
|
||||||
|
+ FAIL_EXIT1 ("error: dlvsym: %s\n", error);
|
||||||
|
+ /* If there was no error, we found a NULL symbol. Return the
|
||||||
|
+ NULL value in this case. */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return sym;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
xdlclose (void *handle)
|
||||||
|
{
|
||||||
|
diff --git a/support/xdlfcn.h b/support/xdlfcn.h
|
||||||
|
index 5ab7494e70924f52..ab1cbb3cb9bb1cc7 100644
|
||||||
|
--- a/support/xdlfcn.h
|
||||||
|
+++ b/support/xdlfcn.h
|
||||||
|
@@ -26,6 +26,7 @@ __BEGIN_DECLS
|
||||||
|
/* Each of these terminates process on failure with relevant error message. */
|
||||||
|
void *xdlopen (const char *filename, int flags);
|
||||||
|
void *xdlsym (void *handle, const char *symbol);
|
||||||
|
+void *xdlvsym (void *handle, const char *symbol, const char *version);
|
||||||
|
void xdlclose (void *handle);
|
||||||
|
|
||||||
|
|
342
SOURCES/glibc-rh1764231-2.patch
Normal file
342
SOURCES/glibc-rh1764231-2.patch
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
commit f0b2132b35248c1f4a80f62a2c38cddcc802aa8c
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Jun 28 10:12:50 2019 +0200
|
||||||
|
|
||||||
|
ld.so: Support moving versioned symbols between sonames [BZ #24741]
|
||||||
|
|
||||||
|
This change should be fully backwards-compatible because the old
|
||||||
|
code aborted the load if a soname mismatch was encountered
|
||||||
|
(instead of searching further for a matching symbol). This means
|
||||||
|
that no different symbols are found.
|
||||||
|
|
||||||
|
The soname check was explicitly disabled for the skip_map != NULL
|
||||||
|
case. However, this only happens with dl(v)sym and RTLD_NEXT,
|
||||||
|
and those lookups do not come with a verneed entry that could be used
|
||||||
|
for the check.
|
||||||
|
|
||||||
|
The error check was already explicitly disabled for the skip_map !=
|
||||||
|
NULL case, that is, when dl(v)sym was called with RTLD_NEXT. But
|
||||||
|
_dl_vsym always sets filename in the struct r_found_version argument
|
||||||
|
to NULL, so the check was not active anyway. This means that
|
||||||
|
symbol lookup results for the skip_map != NULL case do not change,
|
||||||
|
either.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile
|
||||||
|
(usual missing backports)
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 29aa3a96738e4176..73f9e25ea5efd63a 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -187,7 +187,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
|
tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
|
||||||
|
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
|
||||||
|
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
||||||
|
- tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note
|
||||||
|
+ tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
||||||
|
+ tst-sonamemove-link tst-sonamemove-dlopen
|
||||||
|
# reldep9
|
||||||
|
tests-internal += loadtest unload unload2 circleload1 \
|
||||||
|
neededtest neededtest2 neededtest3 neededtest4 \
|
||||||
|
@@ -275,7 +276,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||||
|
tst-latepthreadmod $(tst-tls-many-dynamic-modules) \
|
||||||
|
tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \
|
||||||
|
tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \
|
||||||
|
- tst-absolute-zero-lib tst-big-note-lib
|
||||||
|
+ tst-absolute-zero-lib tst-big-note-lib \
|
||||||
|
+ tst-sonamemove-linkmod1 \
|
||||||
|
+ tst-sonamemove-runmod1 tst-sonamemove-runmod2
|
||||||
|
|
||||||
|
ifeq (yes,$(have-mtls-dialect-gnu2))
|
||||||
|
tests += tst-gnu2-tls1
|
||||||
|
@@ -1374,6 +1377,28 @@ tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so
|
||||||
|
$(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so
|
||||||
|
LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map
|
||||||
|
|
||||||
|
+# tst-sonamemove links against an older implementation of the library.
|
||||||
|
+LDFLAGS-tst-sonamemove-linkmod1.so = \
|
||||||
|
+ -Wl,--version-script=tst-sonamemove-linkmod1.map \
|
||||||
|
+ -Wl,-soname,tst-sonamemove-runmod1.so
|
||||||
|
+LDFLAGS-tst-sonamemove-runmod1.so = -Wl,--no-as-needed \
|
||||||
|
+ -Wl,--version-script=tst-sonamemove-runmod1.map \
|
||||||
|
+ -Wl,-soname,tst-sonamemove-runmod1.so
|
||||||
|
+LDFLAGS-tst-sonamemove-runmod2.so = \
|
||||||
|
+ -Wl,--version-script=tst-sonamemove-runmod2.map \
|
||||||
|
+ -Wl,-soname,tst-sonamemove-runmod2.so
|
||||||
|
+$(objpfx)tst-sonamemove-runmod1.so: $(objpfx)tst-sonamemove-runmod2.so
|
||||||
|
+# Link against the link module, but depend on the run-time modules
|
||||||
|
+# for execution.
|
||||||
|
+$(objpfx)tst-sonamemove-link: $(objpfx)tst-sonamemove-linkmod1.so
|
||||||
|
+$(objpfx)tst-sonamemove-link.out: \
|
||||||
|
+ $(objpfx)tst-sonamemove-runmod1.so \
|
||||||
|
+ $(objpfx)tst-sonamemove-runmod2.so
|
||||||
|
+$(objpfx)tst-sonamemove-dlopen: $(libdl)
|
||||||
|
+$(objpfx)tst-sonamemove-dlopen.out: \
|
||||||
|
+ $(objpfx)tst-sonamemove-runmod1.so \
|
||||||
|
+ $(objpfx)tst-sonamemove-runmod2.so
|
||||||
|
+
|
||||||
|
# Override -z defs, so that we can reference an undefined symbol.
|
||||||
|
# Force lazy binding for the same reason.
|
||||||
|
LDFLAGS-tst-latepthreadmod.so = \
|
||||||
|
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
||||||
|
index 68ecc6179f608547..1d046caf017b582b 100644
|
||||||
|
--- a/elf/dl-lookup.c
|
||||||
|
+++ b/elf/dl-lookup.c
|
||||||
|
@@ -536,11 +536,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
||||||
|
}
|
||||||
|
|
||||||
|
skip:
|
||||||
|
- /* If this current map is the one mentioned in the verneed entry
|
||||||
|
- and we have not found a weak entry, it is a bug. */
|
||||||
|
- if (symidx == STN_UNDEF && version != NULL && version->filename != NULL
|
||||||
|
- && __glibc_unlikely (_dl_name_match_p (version->filename, map)))
|
||||||
|
- return -1;
|
||||||
|
+ ;
|
||||||
|
}
|
||||||
|
while (++i < n);
|
||||||
|
|
||||||
|
@@ -810,34 +806,10 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
||||||
|
|
||||||
|
/* Search the relevant loaded objects for a definition. */
|
||||||
|
for (size_t start = i; *scope != NULL; start = 0, ++scope)
|
||||||
|
- {
|
||||||
|
- int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
|
||||||
|
- ¤t_value, *scope, start, version, flags,
|
||||||
|
- skip_map, type_class, undef_map);
|
||||||
|
- if (res > 0)
|
||||||
|
- break;
|
||||||
|
-
|
||||||
|
- if (__glibc_unlikely (res < 0) && skip_map == NULL)
|
||||||
|
- {
|
||||||
|
- /* Oh, oh. The file named in the relocation entry does not
|
||||||
|
- contain the needed symbol. This code is never reached
|
||||||
|
- for unversioned lookups. */
|
||||||
|
- assert (version != NULL);
|
||||||
|
- const char *reference_name = undef_map ? undef_map->l_name : "";
|
||||||
|
- struct dl_exception exception;
|
||||||
|
- /* XXX We cannot translate the message. */
|
||||||
|
- _dl_exception_create_format
|
||||||
|
- (&exception, DSO_FILENAME (reference_name),
|
||||||
|
- "symbol %s version %s not defined in file %s"
|
||||||
|
- " with link time reference%s",
|
||||||
|
- undef_name, version->name, version->filename,
|
||||||
|
- res == -2 ? " (no version symbols)" : "");
|
||||||
|
- _dl_signal_cexception (0, &exception, N_("relocation error"));
|
||||||
|
- _dl_exception_free (&exception);
|
||||||
|
- *ref = NULL;
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
|
||||||
|
+ ¤t_value, *scope, start, version, flags,
|
||||||
|
+ skip_map, type_class, undef_map) != 0)
|
||||||
|
+ break;
|
||||||
|
|
||||||
|
if (__glibc_unlikely (current_value.s == NULL))
|
||||||
|
{
|
||||||
|
diff --git a/elf/tst-sonamemove-dlopen.c b/elf/tst-sonamemove-dlopen.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..c496705044cdd53c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-sonamemove-dlopen.c
|
||||||
|
@@ -0,0 +1,35 @@
|
||||||
|
+/* Check that a moved versioned symbol can be found using dlsym, dlvsym.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xdlfcn.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* tst-sonamemove-runmod1.so does not define moved_function, but it
|
||||||
|
+ depends on tst-sonamemove-runmod2.so, which does. */
|
||||||
|
+ void *handle = xdlopen ("tst-sonamemove-runmod1.so", RTLD_NOW);
|
||||||
|
+ TEST_VERIFY (xdlsym (handle, "moved_function") != NULL);
|
||||||
|
+ TEST_VERIFY (xdlvsym (handle, "moved_function", "SONAME_MOVE") != NULL);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-sonamemove-link.c b/elf/tst-sonamemove-link.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..4bc3bf32f88f97a9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-sonamemove-link.c
|
||||||
|
@@ -0,0 +1,41 @@
|
||||||
|
+/* Check that a versioned symbol can move from one library to another.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* At link time, moved_function is bound to the symbol version
|
||||||
|
+ SONAME_MOVE in tst-sonamemove-runmod1.so, using the
|
||||||
|
+ tst-sonamemove-linkmod1.so stub object.
|
||||||
|
+
|
||||||
|
+ At run time, the process loads the real tst-sonamemove-runmod1.so,
|
||||||
|
+ which depends on tst-sonamemove-runmod2.so.
|
||||||
|
+ tst-sonamemove-runmod1.so does not define moved_function, but
|
||||||
|
+ tst-sonamemove-runmod2.so does.
|
||||||
|
+
|
||||||
|
+ The net effect is that the versioned symbol
|
||||||
|
+ moved_function@SONAME_MOVE moved from the soname
|
||||||
|
+ tst-sonamemove-linkmod1.so at link time to the soname
|
||||||
|
+ tst-sonamemove-linkmod2.so at run time. */
|
||||||
|
+void moved_function (void);
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ moved_function ();
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-sonamemove-linkmod1.c b/elf/tst-sonamemove-linkmod1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..b8a354e5e394f566
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-sonamemove-linkmod1.c
|
||||||
|
@@ -0,0 +1,25 @@
|
||||||
|
+/* Link interface for (lack of) soname matching in versioned symbol refs.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* This function moved from tst-sonamemove-runmod1.so. This module is
|
||||||
|
+ intended for linking only, to simulate an old application which was
|
||||||
|
+ linked against an older version of the library. */
|
||||||
|
+void
|
||||||
|
+moved_function (void)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-sonamemove-linkmod1.map b/elf/tst-sonamemove-linkmod1.map
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..8fe5904018972009
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-sonamemove-linkmod1.map
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+SONAME_MOVE {
|
||||||
|
+ global: moved_function;
|
||||||
|
+};
|
||||||
|
diff --git a/elf/tst-sonamemove-runmod1.c b/elf/tst-sonamemove-runmod1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..5c409e22898bc836
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-sonamemove-runmod1.c
|
||||||
|
@@ -0,0 +1,23 @@
|
||||||
|
+/* Run-time module whose moved_function moved to a library dependency.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* Dummy function to add the required symbol version. */
|
||||||
|
+void
|
||||||
|
+other_function (void)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-sonamemove-runmod1.map b/elf/tst-sonamemove-runmod1.map
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..2ea81c6e6ffae2be
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-sonamemove-runmod1.map
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+SONAME_MOVE {
|
||||||
|
+ global: other_function;
|
||||||
|
+};
|
||||||
|
diff --git a/elf/tst-sonamemove-runmod2.c b/elf/tst-sonamemove-runmod2.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..b5e482eff57d7d83
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-sonamemove-runmod2.c
|
||||||
|
@@ -0,0 +1,24 @@
|
||||||
|
+/* Run-time module with the actual implementation of moved_function.
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+/* In the test scenario, this function was originally in
|
||||||
|
+ tst-sonamemove-runmod1.so. */
|
||||||
|
+void
|
||||||
|
+moved_function (void)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-sonamemove-runmod2.map b/elf/tst-sonamemove-runmod2.map
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..8fe5904018972009
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-sonamemove-runmod2.map
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+SONAME_MOVE {
|
||||||
|
+ global: moved_function;
|
||||||
|
+};
|
40
SOURCES/glibc-rh1764234-1.patch
Normal file
40
SOURCES/glibc-rh1764234-1.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
commit 47ad5e1a2a3ab8eeda491454cbef3b1c5239dc02
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Tue Jan 1 02:01:02 2019 +0000
|
||||||
|
|
||||||
|
Update syscall-names.list for Linux 4.20.
|
||||||
|
|
||||||
|
This patch updates sysdeps/unix/sysv/linux/syscall-names.list for
|
||||||
|
Linux 4.20. Although there are no new syscalls, the
|
||||||
|
riscv_flush_icache syscall has moved to asm/unistd.h (previously in
|
||||||
|
asm/syscalls.h) and so now needs to be added to the list.
|
||||||
|
|
||||||
|
Tested with build-many-glibcs.py.
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
|
||||||
|
version to 4.20.
|
||||||
|
(riscv_flush_icache): New syscall.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
index 698069a52d..b650dc07cc 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
@@ -22,8 +22,8 @@
|
||||||
|
# names are only used if the installed kernel headers also provide
|
||||||
|
# them.
|
||||||
|
|
||||||
|
-# The list of system calls is current as of Linux 4.19.
|
||||||
|
-kernel 4.19
|
||||||
|
+# The list of system calls is current as of Linux 4.20.
|
||||||
|
+kernel 4.20
|
||||||
|
|
||||||
|
FAST_atomic_update
|
||||||
|
FAST_cmpxchg
|
||||||
|
@@ -431,6 +431,7 @@ renameat
|
||||||
|
renameat2
|
||||||
|
request_key
|
||||||
|
restart_syscall
|
||||||
|
+riscv_flush_icache
|
||||||
|
rmdir
|
||||||
|
rseq
|
||||||
|
rt_sigaction
|
43
SOURCES/glibc-rh1764234-2.patch
Normal file
43
SOURCES/glibc-rh1764234-2.patch
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
commit 477e739b324349df854209117047779ac3142130
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Fri Mar 15 18:18:40 2019 +0000
|
||||||
|
|
||||||
|
Update syscall-names.list for Linux 5.0.
|
||||||
|
|
||||||
|
This patch updates sysdeps/unix/sysv/linux/syscall-names.list for
|
||||||
|
Linux 5.0. Based on testing with build-many-glibcs.py, the only new
|
||||||
|
entry needed is for old_getpagesize (a newly added __NR_* name for an
|
||||||
|
old syscall on ia64). (Because 5.0 changes how syscall tables are
|
||||||
|
handled in the kernel, checking diffs wasn't a useful way of looking
|
||||||
|
for new syscalls in 5.0 as most of the syscall tables were moved to
|
||||||
|
the new representation without actually adding any syscalls to them.)
|
||||||
|
|
||||||
|
Tested with build-many-glibcs.py.
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
|
||||||
|
version to 5.0.
|
||||||
|
(old_getpagesize): New syscall.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
index b650dc07cc..0227e52a5f 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
@@ -22,8 +22,8 @@
|
||||||
|
# names are only used if the installed kernel headers also provide
|
||||||
|
# them.
|
||||||
|
|
||||||
|
-# The list of system calls is current as of Linux 4.20.
|
||||||
|
-kernel 4.20
|
||||||
|
+# The list of system calls is current as of Linux 5.0.
|
||||||
|
+kernel 5.0
|
||||||
|
|
||||||
|
FAST_atomic_update
|
||||||
|
FAST_cmpxchg
|
||||||
|
@@ -261,6 +261,7 @@ nfsservctl
|
||||||
|
ni_syscall
|
||||||
|
nice
|
||||||
|
old_adjtimex
|
||||||
|
+old_getpagesize
|
||||||
|
oldfstat
|
||||||
|
oldlstat
|
||||||
|
oldolduname
|
181
SOURCES/glibc-rh1764234-3.patch
Normal file
181
SOURCES/glibc-rh1764234-3.patch
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
commit 7621676f7a5130c030f7fff1cab72dbf2993b837
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Tue May 7 23:57:26 2019 +0000
|
||||||
|
|
||||||
|
Update syscall-names.list for Linux 5.1.
|
||||||
|
|
||||||
|
This patch updates syscall-names.list for Linux 5.1 (which has many
|
||||||
|
new syscalls, mainly but not entirely ones for 64-bit time).
|
||||||
|
|
||||||
|
Tested with build-many-glibcs.py (before the revert of the move to
|
||||||
|
Linux 5.1 there; verified there were no tst-syscall-list failures).
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
|
||||||
|
version to 5.1.
|
||||||
|
(clock_adjtime64) New syscall.
|
||||||
|
(clock_getres_time64) Likewise.
|
||||||
|
(clock_gettime64) Likewise.
|
||||||
|
(clock_nanosleep_time64) Likewise.
|
||||||
|
(clock_settime64) Likewise.
|
||||||
|
(futex_time64) Likewise.
|
||||||
|
(io_pgetevents_time64) Likewise.
|
||||||
|
(io_uring_enter) Likewise.
|
||||||
|
(io_uring_register) Likewise.
|
||||||
|
(io_uring_setup) Likewise.
|
||||||
|
(mq_timedreceive_time64) Likewise.
|
||||||
|
(mq_timedsend_time64) Likewise.
|
||||||
|
(pidfd_send_signal) Likewise.
|
||||||
|
(ppoll_time64) Likewise.
|
||||||
|
(pselect6_time64) Likewise.
|
||||||
|
(recvmmsg_time64) Likewise.
|
||||||
|
(rt_sigtimedwait_time64) Likewise.
|
||||||
|
(sched_rr_get_interval_time64) Likewise.
|
||||||
|
(semtimedop_time64) Likewise.
|
||||||
|
(timer_gettime64) Likewise.
|
||||||
|
(timer_settime64) Likewise.
|
||||||
|
(timerfd_gettime64) Likewise.
|
||||||
|
(timerfd_settime64) Likewise.
|
||||||
|
(utimensat_time64) Likewise.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
index 0227e52a5f..2d0354b8b3 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
@@ -22,8 +22,8 @@
|
||||||
|
# names are only used if the installed kernel headers also provide
|
||||||
|
# them.
|
||||||
|
|
||||||
|
-# The list of system calls is current as of Linux 5.0.
|
||||||
|
-kernel 5.0
|
||||||
|
+# The list of system calls is current as of Linux 5.1.
|
||||||
|
+kernel 5.1
|
||||||
|
|
||||||
|
FAST_atomic_update
|
||||||
|
FAST_cmpxchg
|
||||||
|
@@ -63,10 +63,15 @@ chown
|
||||||
|
chown32
|
||||||
|
chroot
|
||||||
|
clock_adjtime
|
||||||
|
+clock_adjtime64
|
||||||
|
clock_getres
|
||||||
|
+clock_getres_time64
|
||||||
|
clock_gettime
|
||||||
|
+clock_gettime64
|
||||||
|
clock_nanosleep
|
||||||
|
+clock_nanosleep_time64
|
||||||
|
clock_settime
|
||||||
|
+clock_settime64
|
||||||
|
clone
|
||||||
|
clone2
|
||||||
|
close
|
||||||
|
@@ -128,6 +133,7 @@ ftime
|
||||||
|
ftruncate
|
||||||
|
ftruncate64
|
||||||
|
futex
|
||||||
|
+futex_time64
|
||||||
|
futimesat
|
||||||
|
get_kernel_syms
|
||||||
|
get_mempolicy
|
||||||
|
@@ -187,8 +193,12 @@ io_cancel
|
||||||
|
io_destroy
|
||||||
|
io_getevents
|
||||||
|
io_pgetevents
|
||||||
|
+io_pgetevents_time64
|
||||||
|
io_setup
|
||||||
|
io_submit
|
||||||
|
+io_uring_enter
|
||||||
|
+io_uring_register
|
||||||
|
+io_uring_setup
|
||||||
|
ioctl
|
||||||
|
ioperm
|
||||||
|
iopl
|
||||||
|
@@ -242,7 +252,9 @@ mq_getsetattr
|
||||||
|
mq_notify
|
||||||
|
mq_open
|
||||||
|
mq_timedreceive
|
||||||
|
+mq_timedreceive_time64
|
||||||
|
mq_timedsend
|
||||||
|
+mq_timedsend_time64
|
||||||
|
mq_unlink
|
||||||
|
mremap
|
||||||
|
msgctl
|
||||||
|
@@ -389,6 +401,7 @@ perf_event_open
|
||||||
|
perfctr
|
||||||
|
perfmonctl
|
||||||
|
personality
|
||||||
|
+pidfd_send_signal
|
||||||
|
pipe
|
||||||
|
pipe2
|
||||||
|
pivot_root
|
||||||
|
@@ -397,6 +410,7 @@ pkey_free
|
||||||
|
pkey_mprotect
|
||||||
|
poll
|
||||||
|
ppoll
|
||||||
|
+ppoll_time64
|
||||||
|
prctl
|
||||||
|
pread64
|
||||||
|
preadv
|
||||||
|
@@ -407,6 +421,7 @@ process_vm_writev
|
||||||
|
prof
|
||||||
|
profil
|
||||||
|
pselect6
|
||||||
|
+pselect6_time64
|
||||||
|
ptrace
|
||||||
|
putpmsg
|
||||||
|
pwrite64
|
||||||
|
@@ -424,6 +439,7 @@ reboot
|
||||||
|
recv
|
||||||
|
recvfrom
|
||||||
|
recvmmsg
|
||||||
|
+recvmmsg_time64
|
||||||
|
recvmsg
|
||||||
|
remap_file_pages
|
||||||
|
removexattr
|
||||||
|
@@ -442,6 +458,7 @@ rt_sigqueueinfo
|
||||||
|
rt_sigreturn
|
||||||
|
rt_sigsuspend
|
||||||
|
rt_sigtimedwait
|
||||||
|
+rt_sigtimedwait_time64
|
||||||
|
rt_tgsigqueueinfo
|
||||||
|
rtas
|
||||||
|
s390_guarded_storage
|
||||||
|
@@ -457,6 +474,7 @@ sched_getattr
|
||||||
|
sched_getparam
|
||||||
|
sched_getscheduler
|
||||||
|
sched_rr_get_interval
|
||||||
|
+sched_rr_get_interval_time64
|
||||||
|
sched_set_affinity
|
||||||
|
sched_setaffinity
|
||||||
|
sched_setattr
|
||||||
|
@@ -470,6 +488,7 @@ semctl
|
||||||
|
semget
|
||||||
|
semop
|
||||||
|
semtimedop
|
||||||
|
+semtimedop_time64
|
||||||
|
send
|
||||||
|
sendfile
|
||||||
|
sendfile64
|
||||||
|
@@ -567,11 +586,15 @@ timer_create
|
||||||
|
timer_delete
|
||||||
|
timer_getoverrun
|
||||||
|
timer_gettime
|
||||||
|
+timer_gettime64
|
||||||
|
timer_settime
|
||||||
|
+timer_settime64
|
||||||
|
timerfd
|
||||||
|
timerfd_create
|
||||||
|
timerfd_gettime
|
||||||
|
+timerfd_gettime64
|
||||||
|
timerfd_settime
|
||||||
|
+timerfd_settime64
|
||||||
|
times
|
||||||
|
tkill
|
||||||
|
truncate
|
||||||
|
@@ -591,6 +614,7 @@ userfaultfd
|
||||||
|
ustat
|
||||||
|
utime
|
||||||
|
utimensat
|
||||||
|
+utimensat_time64
|
||||||
|
utimes
|
||||||
|
utrap_install
|
||||||
|
vfork
|
58
SOURCES/glibc-rh1764234-4.patch
Normal file
58
SOURCES/glibc-rh1764234-4.patch
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
commit 0bb8f8c791862a4ff38a584af23bbb5bf3f90acd
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri May 31 13:52:16 2019 +0200
|
||||||
|
|
||||||
|
Linux: Add oddly-named arm syscalls to syscall-names.list
|
||||||
|
|
||||||
|
<asm/unistd.h> on arm defines the following macros:
|
||||||
|
|
||||||
|
#define __ARM_NR_breakpoint (__ARM_NR_BASE+1)
|
||||||
|
#define __ARM_NR_cacheflush (__ARM_NR_BASE+2)
|
||||||
|
#define __ARM_NR_usr26 (__ARM_NR_BASE+3)
|
||||||
|
#define __ARM_NR_usr32 (__ARM_NR_BASE+4)
|
||||||
|
#define __ARM_NR_set_tls (__ARM_NR_BASE+5)
|
||||||
|
#define __ARM_NR_get_tls (__ARM_NR_BASE+6)
|
||||||
|
|
||||||
|
These do not follow the regular __NR_* naming convention and
|
||||||
|
have so far been ignored by the syscall-names.list consistency
|
||||||
|
checks. This commit adds these names to the file, preparing
|
||||||
|
for the availability of these names in the regular __NR_*
|
||||||
|
namespace.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
index 2d0354b8b3..ae8adabb70 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
@@ -52,6 +52,7 @@ bdflush
|
||||||
|
bind
|
||||||
|
bpf
|
||||||
|
break
|
||||||
|
+breakpoint
|
||||||
|
brk
|
||||||
|
cachectl
|
||||||
|
cacheflush
|
||||||
|
@@ -139,6 +140,7 @@ get_kernel_syms
|
||||||
|
get_mempolicy
|
||||||
|
get_robust_list
|
||||||
|
get_thread_area
|
||||||
|
+get_tls
|
||||||
|
getcpu
|
||||||
|
getcwd
|
||||||
|
getdents
|
||||||
|
@@ -499,6 +501,7 @@ set_mempolicy
|
||||||
|
set_robust_list
|
||||||
|
set_thread_area
|
||||||
|
set_tid_address
|
||||||
|
+set_tls
|
||||||
|
setdomainname
|
||||||
|
setfsgid
|
||||||
|
setfsgid32
|
||||||
|
@@ -611,6 +614,8 @@ unlinkat
|
||||||
|
unshare
|
||||||
|
uselib
|
||||||
|
userfaultfd
|
||||||
|
+usr26
|
||||||
|
+usr32
|
||||||
|
ustat
|
||||||
|
utime
|
||||||
|
utimensat
|
30
SOURCES/glibc-rh1764234-5.patch
Normal file
30
SOURCES/glibc-rh1764234-5.patch
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
commit a63b96fbddbf97feaa068a9efed3b5623a1a1e78
|
||||||
|
Author: Vincent Chen <vincentc@andestech.com>
|
||||||
|
Date: Wed Jun 26 17:30:11 2019 +0800
|
||||||
|
|
||||||
|
Linux: Add nds32 specific syscalls to syscall-names.list
|
||||||
|
|
||||||
|
The nds32 creates two specific syscalls, udftrap and fp_udfiex_crtl, in
|
||||||
|
kernel v5.0 and v5.2, respectively. Add these two syscalls to
|
||||||
|
syscall-names.list.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
index ae8adabb70..95aa3ec7a5 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
@@ -121,6 +121,7 @@ finit_module
|
||||||
|
flistxattr
|
||||||
|
flock
|
||||||
|
fork
|
||||||
|
+fp_udfiex_crtl
|
||||||
|
free_hugepages
|
||||||
|
fremovexattr
|
||||||
|
fsetxattr
|
||||||
|
@@ -603,6 +604,7 @@ tkill
|
||||||
|
truncate
|
||||||
|
truncate64
|
||||||
|
tuxcall
|
||||||
|
+udftrap
|
||||||
|
ugetrlimit
|
||||||
|
ulimit
|
||||||
|
umask
|
52
SOURCES/glibc-rh1764234-6.patch
Normal file
52
SOURCES/glibc-rh1764234-6.patch
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
commit 1f7097d09ce628878107ed30341cfc1eb3649a81
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Jul 19 08:53:04 2019 +0200
|
||||||
|
|
||||||
|
Linux: Update syscall-names.list to Linux 5.2
|
||||||
|
|
||||||
|
This adds the system call names fsconfig, fsmount, fsopen, fspick,
|
||||||
|
move_mount, open_tree.
|
||||||
|
|
||||||
|
Tested with build-many-glibcs.py.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
index 95aa3ec7a5..21bf37c627 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
@@ -23,7 +23,7 @@
|
||||||
|
# them.
|
||||||
|
|
||||||
|
# The list of system calls is current as of Linux 5.1.
|
||||||
|
-kernel 5.1
|
||||||
|
+kernel 5.2
|
||||||
|
|
||||||
|
FAST_atomic_update
|
||||||
|
FAST_cmpxchg
|
||||||
|
@@ -124,7 +124,11 @@ fork
|
||||||
|
fp_udfiex_crtl
|
||||||
|
free_hugepages
|
||||||
|
fremovexattr
|
||||||
|
+fsconfig
|
||||||
|
fsetxattr
|
||||||
|
+fsmount
|
||||||
|
+fsopen
|
||||||
|
+fspick
|
||||||
|
fstat
|
||||||
|
fstat64
|
||||||
|
fstatat64
|
||||||
|
@@ -248,6 +252,7 @@ mmap
|
||||||
|
mmap2
|
||||||
|
modify_ldt
|
||||||
|
mount
|
||||||
|
+move_mount
|
||||||
|
move_pages
|
||||||
|
mprotect
|
||||||
|
mpx
|
||||||
|
@@ -285,6 +290,7 @@ oldumount
|
||||||
|
olduname
|
||||||
|
open
|
||||||
|
open_by_handle_at
|
||||||
|
+open_tree
|
||||||
|
openat
|
||||||
|
osf_adjtime
|
||||||
|
osf_afs_syscall
|
24
SOURCES/glibc-rh1764234-7.patch
Normal file
24
SOURCES/glibc-rh1764234-7.patch
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
commit 9c37bde5a2067e5b4dc878bac0291d6b207b8add
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Fri Aug 2 15:08:02 2019 +0000
|
||||||
|
|
||||||
|
Update kernel version in comment in syscall-names.list.
|
||||||
|
|
||||||
|
This patch updates the Linux kernel version in a comment in
|
||||||
|
syscall-names.list to agree with the following "kernel" line.
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/syscall-names.list: Update comment.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
index 21bf37c627..9dcdd293d3 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
@@ -22,7 +22,7 @@
|
||||||
|
# names are only used if the installed kernel headers also provide
|
||||||
|
# them.
|
||||||
|
|
||||||
|
-# The list of system calls is current as of Linux 5.1.
|
||||||
|
+# The list of system calls is current as of Linux 5.2.
|
||||||
|
kernel 5.2
|
||||||
|
|
||||||
|
FAST_atomic_update
|
47
SOURCES/glibc-rh1764234-8.patch
Normal file
47
SOURCES/glibc-rh1764234-8.patch
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
commit 0f02b6cfc44af73d4d4363c46b3cbb18b8ff9171
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Wed Sep 18 22:57:46 2019 +0000
|
||||||
|
|
||||||
|
Update syscall-names.list for Linux 5.3.
|
||||||
|
|
||||||
|
This patch updates syscall-names.list for Linux 5.3, adding two new
|
||||||
|
syscalls.
|
||||||
|
|
||||||
|
Tested with build-many-glibcs.py.
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
|
||||||
|
version to 5.3.
|
||||||
|
(clone3): New syscall.
|
||||||
|
(pidfd_open): Likewise.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
index e2382d3414..b55ffbc2a0 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||||
|
@@ -22,8 +22,8 @@
|
||||||
|
# names are only used if the installed kernel headers also provide
|
||||||
|
# them.
|
||||||
|
|
||||||
|
-# The list of system calls is current as of Linux 5.2.
|
||||||
|
-kernel 5.2
|
||||||
|
+# The list of system calls is current as of Linux 5.3.
|
||||||
|
+kernel 5.3
|
||||||
|
|
||||||
|
FAST_atomic_update
|
||||||
|
FAST_cmpxchg
|
||||||
|
@@ -75,6 +75,7 @@ clock_settime
|
||||||
|
clock_settime64
|
||||||
|
clone
|
||||||
|
clone2
|
||||||
|
+clone3
|
||||||
|
close
|
||||||
|
cmpxchg_badaddr
|
||||||
|
connect
|
||||||
|
@@ -410,6 +411,7 @@ perf_event_open
|
||||||
|
perfctr
|
||||||
|
perfmonctl
|
||||||
|
personality
|
||||||
|
+pidfd_open
|
||||||
|
pidfd_send_signal
|
||||||
|
pipe
|
||||||
|
pipe2
|
165
SOURCES/glibc-rh1764235.patch
Normal file
165
SOURCES/glibc-rh1764235.patch
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
commit e621246ec6393ea08ae50310f9d5e72500f8c9bc
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Mon Apr 8 17:35:05 2019 -0400
|
||||||
|
|
||||||
|
malloc: Set and reset all hooks for tracing (Bug 16573)
|
||||||
|
|
||||||
|
If an error occurs during the tracing operation, particularly during a
|
||||||
|
call to lock_and_info() which calls _dl_addr, we may end up calling back
|
||||||
|
into the malloc-subsystem and relock the loader lock and deadlock. For
|
||||||
|
all intents and purposes the call to _dl_addr can call any of the malloc
|
||||||
|
family API functions and so we should disable all tracing before calling
|
||||||
|
such loader functions. This is similar to the strategy that the new
|
||||||
|
malloc tracer takes when calling the real malloc, namely that all
|
||||||
|
tracing ceases at the boundary to the real function and any faults at
|
||||||
|
that point are the purvue of the library (though the new tracer does
|
||||||
|
this on a per-thread basis in an MT-safe fashion). Since the new tracer
|
||||||
|
and the hook deprecation are not yet complete we must fix these issues
|
||||||
|
where we can.
|
||||||
|
|
||||||
|
Tested on x86_64 with no regressions.
|
||||||
|
|
||||||
|
Co-authored-by: Kwok Cheung Yeung <kcy@codesourcery.com>
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/malloc/mtrace.c b/malloc/mtrace.c
|
||||||
|
index 9064f209ec3b24c6..546d37a26018bf41 100644
|
||||||
|
--- a/malloc/mtrace.c
|
||||||
|
+++ b/malloc/mtrace.c
|
||||||
|
@@ -121,6 +121,41 @@ lock_and_info (const void *caller, Dl_info *mem)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void tr_freehook (void *, const void *);
|
||||||
|
+static void * tr_mallochook (size_t, const void *);
|
||||||
|
+static void * tr_reallochook (void *, size_t, const void *);
|
||||||
|
+static void * tr_memalignhook (size_t, size_t, const void *);
|
||||||
|
+
|
||||||
|
+/* Set all the default non-trace hooks. */
|
||||||
|
+static __always_inline void
|
||||||
|
+set_default_hooks (void)
|
||||||
|
+{
|
||||||
|
+ __free_hook = tr_old_free_hook;
|
||||||
|
+ __malloc_hook = tr_old_malloc_hook;
|
||||||
|
+ __realloc_hook = tr_old_realloc_hook;
|
||||||
|
+ __memalign_hook = tr_old_memalign_hook;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Set all of the tracing hooks used for mtrace. */
|
||||||
|
+static __always_inline void
|
||||||
|
+set_trace_hooks (void)
|
||||||
|
+{
|
||||||
|
+ __free_hook = tr_freehook;
|
||||||
|
+ __malloc_hook = tr_mallochook;
|
||||||
|
+ __realloc_hook = tr_reallochook;
|
||||||
|
+ __memalign_hook = tr_memalignhook;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Save the current set of hooks as the default hooks. */
|
||||||
|
+static __always_inline void
|
||||||
|
+save_default_hooks (void)
|
||||||
|
+{
|
||||||
|
+ tr_old_free_hook = __free_hook;
|
||||||
|
+ tr_old_malloc_hook = __malloc_hook;
|
||||||
|
+ tr_old_realloc_hook = __realloc_hook;
|
||||||
|
+ tr_old_memalign_hook = __memalign_hook;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
tr_freehook (void *ptr, const void *caller)
|
||||||
|
{
|
||||||
|
@@ -138,12 +173,12 @@ tr_freehook (void *ptr, const void *caller)
|
||||||
|
tr_break ();
|
||||||
|
__libc_lock_lock (lock);
|
||||||
|
}
|
||||||
|
- __free_hook = tr_old_free_hook;
|
||||||
|
+ set_default_hooks ();
|
||||||
|
if (tr_old_free_hook != NULL)
|
||||||
|
(*tr_old_free_hook)(ptr, caller);
|
||||||
|
else
|
||||||
|
free (ptr);
|
||||||
|
- __free_hook = tr_freehook;
|
||||||
|
+ set_trace_hooks ();
|
||||||
|
__libc_lock_unlock (lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -155,12 +190,12 @@ tr_mallochook (size_t size, const void *caller)
|
||||||
|
Dl_info mem;
|
||||||
|
Dl_info *info = lock_and_info (caller, &mem);
|
||||||
|
|
||||||
|
- __malloc_hook = tr_old_malloc_hook;
|
||||||
|
+ set_default_hooks ();
|
||||||
|
if (tr_old_malloc_hook != NULL)
|
||||||
|
hdr = (void *) (*tr_old_malloc_hook)(size, caller);
|
||||||
|
else
|
||||||
|
hdr = (void *) malloc (size);
|
||||||
|
- __malloc_hook = tr_mallochook;
|
||||||
|
+ set_trace_hooks ();
|
||||||
|
|
||||||
|
tr_where (caller, info);
|
||||||
|
/* We could be printing a NULL here; that's OK. */
|
||||||
|
@@ -185,16 +220,12 @@ tr_reallochook (void *ptr, size_t size, const void *caller)
|
||||||
|
Dl_info mem;
|
||||||
|
Dl_info *info = lock_and_info (caller, &mem);
|
||||||
|
|
||||||
|
- __free_hook = tr_old_free_hook;
|
||||||
|
- __malloc_hook = tr_old_malloc_hook;
|
||||||
|
- __realloc_hook = tr_old_realloc_hook;
|
||||||
|
+ set_default_hooks ();
|
||||||
|
if (tr_old_realloc_hook != NULL)
|
||||||
|
hdr = (void *) (*tr_old_realloc_hook)(ptr, size, caller);
|
||||||
|
else
|
||||||
|
hdr = (void *) realloc (ptr, size);
|
||||||
|
- __free_hook = tr_freehook;
|
||||||
|
- __malloc_hook = tr_mallochook;
|
||||||
|
- __realloc_hook = tr_reallochook;
|
||||||
|
+ set_trace_hooks ();
|
||||||
|
|
||||||
|
tr_where (caller, info);
|
||||||
|
if (hdr == NULL)
|
||||||
|
@@ -230,14 +261,12 @@ tr_memalignhook (size_t alignment, size_t size, const void *caller)
|
||||||
|
Dl_info mem;
|
||||||
|
Dl_info *info = lock_and_info (caller, &mem);
|
||||||
|
|
||||||
|
- __memalign_hook = tr_old_memalign_hook;
|
||||||
|
- __malloc_hook = tr_old_malloc_hook;
|
||||||
|
+ set_default_hooks ();
|
||||||
|
if (tr_old_memalign_hook != NULL)
|
||||||
|
hdr = (void *) (*tr_old_memalign_hook)(alignment, size, caller);
|
||||||
|
else
|
||||||
|
hdr = (void *) memalign (alignment, size);
|
||||||
|
- __memalign_hook = tr_memalignhook;
|
||||||
|
- __malloc_hook = tr_mallochook;
|
||||||
|
+ set_trace_hooks ();
|
||||||
|
|
||||||
|
tr_where (caller, info);
|
||||||
|
/* We could be printing a NULL here; that's OK. */
|
||||||
|
@@ -305,14 +334,8 @@ mtrace (void)
|
||||||
|
malloc_trace_buffer = mtb;
|
||||||
|
setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
|
||||||
|
fprintf (mallstream, "= Start\n");
|
||||||
|
- tr_old_free_hook = __free_hook;
|
||||||
|
- __free_hook = tr_freehook;
|
||||||
|
- tr_old_malloc_hook = __malloc_hook;
|
||||||
|
- __malloc_hook = tr_mallochook;
|
||||||
|
- tr_old_realloc_hook = __realloc_hook;
|
||||||
|
- __realloc_hook = tr_reallochook;
|
||||||
|
- tr_old_memalign_hook = __memalign_hook;
|
||||||
|
- __memalign_hook = tr_memalignhook;
|
||||||
|
+ save_default_hooks ();
|
||||||
|
+ set_trace_hooks ();
|
||||||
|
#ifdef _LIBC
|
||||||
|
if (!added_atexit_handler)
|
||||||
|
{
|
||||||
|
@@ -338,10 +361,7 @@ muntrace (void)
|
||||||
|
file. */
|
||||||
|
FILE *f = mallstream;
|
||||||
|
mallstream = NULL;
|
||||||
|
- __free_hook = tr_old_free_hook;
|
||||||
|
- __malloc_hook = tr_old_malloc_hook;
|
||||||
|
- __realloc_hook = tr_old_realloc_hook;
|
||||||
|
- __memalign_hook = tr_old_memalign_hook;
|
||||||
|
+ set_default_hooks ();
|
||||||
|
|
||||||
|
fprintf (f, "= End\n");
|
||||||
|
fclose (f);
|
92
SOURCES/glibc-rh1764238-1.patch
Normal file
92
SOURCES/glibc-rh1764238-1.patch
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
commit dc0afac3252d0c53716ccaf0b424f7769a66d695
|
||||||
|
Author: marxin <mliska@suse.cz>
|
||||||
|
Date: Wed Feb 20 14:54:35 2019 +0100
|
||||||
|
|
||||||
|
Add new Fortran vector math header file.
|
||||||
|
|
||||||
|
diff --git a/bits/math-vector-fortran.h b/bits/math-vector-fortran.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..7c1e095094e24571
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/bits/math-vector-fortran.h
|
||||||
|
@@ -0,0 +1,19 @@
|
||||||
|
+! Platform-specific declarations of SIMD math functions for Fortran. -*- f90 -*-
|
||||||
|
+! Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+! This file is part of the GNU C Library.
|
||||||
|
+!
|
||||||
|
+! The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+! modify it under the terms of the GNU Lesser General Public
|
||||||
|
+! License as published by the Free Software Foundation; either
|
||||||
|
+! version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+!
|
||||||
|
+! The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+! Lesser General Public License for more details.
|
||||||
|
+!
|
||||||
|
+! You should have received a copy of the GNU Lesser General Public
|
||||||
|
+! License along with the GNU C Library; if not, see
|
||||||
|
+! <http://www.gnu.org/licenses/>.
|
||||||
|
+
|
||||||
|
+! No SIMD math functions are available for this platform.
|
||||||
|
diff --git a/math/Makefile b/math/Makefile
|
||||||
|
index 90b3b68916e12d85..16e68754fc863ea2 100644
|
||||||
|
--- a/math/Makefile
|
||||||
|
+++ b/math/Makefile
|
||||||
|
@@ -26,6 +26,7 @@ headers := math.h bits/mathcalls.h bits/mathinline.h \
|
||||||
|
fpu_control.h complex.h bits/cmathcalls.h fenv.h \
|
||||||
|
bits/fenv.h bits/fenvinline.h bits/mathdef.h tgmath.h \
|
||||||
|
bits/math-finite.h bits/math-vector.h \
|
||||||
|
+ bits/math-vector-fortran.h \
|
||||||
|
bits/libm-simd-decl-stubs.h bits/iscanonical.h \
|
||||||
|
bits/flt-eval-method.h bits/fp-fast.h bits/fp-logb.h \
|
||||||
|
bits/long-double.h bits/mathcalls-helper-functions.h \
|
||||||
|
diff --git a/sysdeps/x86/fpu/bits/math-vector-fortran.h b/sysdeps/x86/fpu/bits/math-vector-fortran.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..36051cc73ea03602
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86/fpu/bits/math-vector-fortran.h
|
||||||
|
@@ -0,0 +1,43 @@
|
||||||
|
+! Platform-specific declarations of SIMD math functions for Fortran. -*- f90 -*-
|
||||||
|
+! Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+! This file is part of the GNU C Library.
|
||||||
|
+!
|
||||||
|
+! The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+! modify it under the terms of the GNU Lesser General Public
|
||||||
|
+! License as published by the Free Software Foundation; either
|
||||||
|
+! version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+!
|
||||||
|
+! The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+! Lesser General Public License for more details.
|
||||||
|
+!
|
||||||
|
+! You should have received a copy of the GNU Lesser General Public
|
||||||
|
+! License along with the GNU C Library; if not, see
|
||||||
|
+! <http://www.gnu.org/licenses/>.
|
||||||
|
+
|
||||||
|
+!GCC$ builtin (cos) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (cosf) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (sin) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (sinf) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (sincos) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (sincosf) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (log) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (logf) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (exp) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (expf) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (pow) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+!GCC$ builtin (powf) attributes simd (notinbranch) if('x86_64')
|
||||||
|
+
|
||||||
|
+!GCC$ builtin (cos) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (cosf) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (sin) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (sinf) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (sincos) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (sincosf) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (log) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (logf) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (exp) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (expf) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (pow) attributes simd (notinbranch) if('x32')
|
||||||
|
+!GCC$ builtin (powf) attributes simd (notinbranch) if('x32')
|
56
SOURCES/glibc-rh1764238-2.patch
Normal file
56
SOURCES/glibc-rh1764238-2.patch
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
commit ae514971341dcc08ec7f8622493a65e7eb1ef9d2
|
||||||
|
Author: marxin <mliska@suse.cz>
|
||||||
|
Date: Thu Mar 7 09:39:55 2019 +0100
|
||||||
|
|
||||||
|
Fix location where math-vector-fortran.h is installed.
|
||||||
|
|
||||||
|
2019-03-07 Martin Liska <mliska@suse.cz>
|
||||||
|
|
||||||
|
* math/Makefile: Change location where math-vector-fortran.h is
|
||||||
|
installed.
|
||||||
|
* math/finclude/math-vector-fortran.h: Move from bits/math-vector-fortran.h.
|
||||||
|
* sysdeps/x86/fpu/finclude/math-vector-fortran.h: Move
|
||||||
|
from sysdeps/x86/fpu/bits/math-vector-fortran.h.
|
||||||
|
* scripts/check-installed-headers.sh: Skip Fortran header files.
|
||||||
|
* scripts/check-wrapper-headers.py: Likewise.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
scripts/check-wrapper-headers.py
|
||||||
|
(Script does not exist downstream, change dropped.)
|
||||||
|
|
||||||
|
diff --git a/math/Makefile b/math/Makefile
|
||||||
|
index 16e68754fc863ea2..df73d70840b61cd7 100644
|
||||||
|
--- a/math/Makefile
|
||||||
|
+++ b/math/Makefile
|
||||||
|
@@ -26,7 +26,7 @@ headers := math.h bits/mathcalls.h bits/mathinline.h \
|
||||||
|
fpu_control.h complex.h bits/cmathcalls.h fenv.h \
|
||||||
|
bits/fenv.h bits/fenvinline.h bits/mathdef.h tgmath.h \
|
||||||
|
bits/math-finite.h bits/math-vector.h \
|
||||||
|
- bits/math-vector-fortran.h \
|
||||||
|
+ finclude/math-vector-fortran.h \
|
||||||
|
bits/libm-simd-decl-stubs.h bits/iscanonical.h \
|
||||||
|
bits/flt-eval-method.h bits/fp-fast.h bits/fp-logb.h \
|
||||||
|
bits/long-double.h bits/mathcalls-helper-functions.h \
|
||||||
|
diff --git a/bits/math-vector-fortran.h b/math/finclude/math-vector-fortran.h
|
||||||
|
similarity index 100%
|
||||||
|
rename from bits/math-vector-fortran.h
|
||||||
|
rename to math/finclude/math-vector-fortran.h
|
||||||
|
diff --git a/scripts/check-installed-headers.sh b/scripts/check-installed-headers.sh
|
||||||
|
index 4a062e9cdaa57978..7a1969b43a144ebb 100644
|
||||||
|
--- a/scripts/check-installed-headers.sh
|
||||||
|
+++ b/scripts/check-installed-headers.sh
|
||||||
|
@@ -84,6 +84,10 @@ for header in "$@"; do
|
||||||
|
(sys/elf.h)
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
+ # Skip Fortran headers.
|
||||||
|
+ (finclude/*)
|
||||||
|
+ continue;;
|
||||||
|
+
|
||||||
|
# sys/sysctl.h is unsupported for x32.
|
||||||
|
(sys/sysctl.h)
|
||||||
|
case "$is_x32" in
|
||||||
|
diff --git a/sysdeps/x86/fpu/bits/math-vector-fortran.h b/sysdeps/x86/fpu/finclude/math-vector-fortran.h
|
||||||
|
similarity index 100%
|
||||||
|
rename from sysdeps/x86/fpu/bits/math-vector-fortran.h
|
||||||
|
rename to sysdeps/x86/fpu/finclude/math-vector-fortran.h
|
544
SOURCES/glibc-rh1764241.patch
Normal file
544
SOURCES/glibc-rh1764241.patch
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
commit 09e1b0e3f6facc1af2dbcfef204f0aaa8718772b
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon May 20 21:54:57 2019 +0200
|
||||||
|
|
||||||
|
libio: Remove codecvt vtable [BZ #24588]
|
||||||
|
|
||||||
|
The codecvt vtable is not a real vtable because it also contains the
|
||||||
|
conversion state data. Furthermore, wide stream support was added to
|
||||||
|
GCC 3.0, after a C++ ABI bump, so there is no compatibility
|
||||||
|
requirement with libstdc++.
|
||||||
|
|
||||||
|
This change removes several unmangled function pointers which could
|
||||||
|
be used with a corrupted FILE object to redirect execution. (libio
|
||||||
|
vtable verification did not cover the codecvt vtable.)
|
||||||
|
|
||||||
|
Reviewed-by: Yann Droneaud <ydroneaud@opteya.com>
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/libio/fileops.c b/libio/fileops.c
|
||||||
|
index d2070a856e..daa5a05877 100644
|
||||||
|
--- a/libio/fileops.c
|
||||||
|
+++ b/libio/fileops.c
|
||||||
|
@@ -331,9 +331,6 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode,
|
||||||
|
|
||||||
|
cc = fp->_codecvt = &fp->_wide_data->_codecvt;
|
||||||
|
|
||||||
|
- /* The functions are always the same. */
|
||||||
|
- *cc = __libio_codecvt;
|
||||||
|
-
|
||||||
|
cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
|
||||||
|
cc->__cd_in.__cd.__steps = fcts.towc;
|
||||||
|
|
||||||
|
diff --git a/libio/iofgetpos.c b/libio/iofgetpos.c
|
||||||
|
index 8032192440..388c4a0708 100644
|
||||||
|
--- a/libio/iofgetpos.c
|
||||||
|
+++ b/libio/iofgetpos.c
|
||||||
|
@@ -70,8 +70,7 @@ _IO_new_fgetpos (FILE *fp, __fpos_t *posp)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
posp->__pos = pos;
|
||||||
|
- if (fp->_mode > 0
|
||||||
|
- && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
|
||||||
|
+ if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0)
|
||||||
|
/* This is a stateful encoding, safe the state. */
|
||||||
|
posp->__state = fp->_wide_data->_IO_state;
|
||||||
|
}
|
||||||
|
diff --git a/libio/iofgetpos64.c b/libio/iofgetpos64.c
|
||||||
|
index 54de6a8205..6a0ba50d29 100644
|
||||||
|
--- a/libio/iofgetpos64.c
|
||||||
|
+++ b/libio/iofgetpos64.c
|
||||||
|
@@ -54,8 +54,7 @@ _IO_new_fgetpos64 (FILE *fp, __fpos64_t *posp)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
posp->__pos = pos;
|
||||||
|
- if (fp->_mode > 0
|
||||||
|
- && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
|
||||||
|
+ if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0)
|
||||||
|
/* This is a stateful encoding, safe the state. */
|
||||||
|
posp->__state = fp->_wide_data->_IO_state;
|
||||||
|
}
|
||||||
|
diff --git a/libio/iofsetpos.c b/libio/iofsetpos.c
|
||||||
|
index d7b1abbc61..4df1aae082 100644
|
||||||
|
--- a/libio/iofsetpos.c
|
||||||
|
+++ b/libio/iofsetpos.c
|
||||||
|
@@ -58,8 +58,7 @@ _IO_new_fsetpos (FILE *fp, const __fpos_t *posp)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
- if (fp->_mode > 0
|
||||||
|
- && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
|
||||||
|
+ if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0)
|
||||||
|
/* This is a stateful encoding, restore the state. */
|
||||||
|
fp->_wide_data->_IO_state = posp->__state;
|
||||||
|
}
|
||||||
|
diff --git a/libio/iofsetpos64.c b/libio/iofsetpos64.c
|
||||||
|
index d1865b728e..f382ba0dc1 100644
|
||||||
|
--- a/libio/iofsetpos64.c
|
||||||
|
+++ b/libio/iofsetpos64.c
|
||||||
|
@@ -48,8 +48,7 @@ _IO_new_fsetpos64 (FILE *fp, const fpos64_t *posp)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
- if (fp->_mode > 0
|
||||||
|
- && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
|
||||||
|
+ if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0)
|
||||||
|
/* This is a stateful encoding, safe the state. */
|
||||||
|
fp->_wide_data->_IO_state = posp->__state;
|
||||||
|
}
|
||||||
|
diff --git a/libio/iofwide.c b/libio/iofwide.c
|
||||||
|
index 247cfde3d0..80cb2d5074 100644
|
||||||
|
--- a/libio/iofwide.c
|
||||||
|
+++ b/libio/iofwide.c
|
||||||
|
@@ -39,44 +39,6 @@
|
||||||
|
#include <sysdep.h>
|
||||||
|
|
||||||
|
|
||||||
|
-/* Prototypes of libio's codecvt functions. */
|
||||||
|
-static enum __codecvt_result do_out (struct _IO_codecvt *codecvt,
|
||||||
|
- __mbstate_t *statep,
|
||||||
|
- const wchar_t *from_start,
|
||||||
|
- const wchar_t *from_end,
|
||||||
|
- const wchar_t **from_stop, char *to_start,
|
||||||
|
- char *to_end, char **to_stop);
|
||||||
|
-static enum __codecvt_result do_unshift (struct _IO_codecvt *codecvt,
|
||||||
|
- __mbstate_t *statep, char *to_start,
|
||||||
|
- char *to_end, char **to_stop);
|
||||||
|
-static enum __codecvt_result do_in (struct _IO_codecvt *codecvt,
|
||||||
|
- __mbstate_t *statep,
|
||||||
|
- const char *from_start,
|
||||||
|
- const char *from_end,
|
||||||
|
- const char **from_stop, wchar_t *to_start,
|
||||||
|
- wchar_t *to_end, wchar_t **to_stop);
|
||||||
|
-static int do_encoding (struct _IO_codecvt *codecvt);
|
||||||
|
-static int do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
- const char *from_start,
|
||||||
|
- const char *from_end, size_t max);
|
||||||
|
-static int do_max_length (struct _IO_codecvt *codecvt);
|
||||||
|
-static int do_always_noconv (struct _IO_codecvt *codecvt);
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* The functions used in `codecvt' for libio are always the same. */
|
||||||
|
-const struct _IO_codecvt __libio_codecvt =
|
||||||
|
-{
|
||||||
|
- .__codecvt_destr = NULL, /* Destructor, never used. */
|
||||||
|
- .__codecvt_do_out = do_out,
|
||||||
|
- .__codecvt_do_unshift = do_unshift,
|
||||||
|
- .__codecvt_do_in = do_in,
|
||||||
|
- .__codecvt_do_encoding = do_encoding,
|
||||||
|
- .__codecvt_do_always_noconv = do_always_noconv,
|
||||||
|
- .__codecvt_do_length = do_length,
|
||||||
|
- .__codecvt_do_max_length = do_max_length
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-
|
||||||
|
/* Return orientation of stream. If mode is nonzero try to change
|
||||||
|
the orientation first. */
|
||||||
|
#undef _IO_fwide
|
||||||
|
@@ -118,9 +80,6 @@ _IO_fwide (FILE *fp, int mode)
|
||||||
|
assert (fcts.towc_nsteps == 1);
|
||||||
|
assert (fcts.tomb_nsteps == 1);
|
||||||
|
|
||||||
|
- /* The functions are always the same. */
|
||||||
|
- *cc = __libio_codecvt;
|
||||||
|
-
|
||||||
|
cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
|
||||||
|
cc->__cd_in.__cd.__steps = fcts.towc;
|
||||||
|
|
||||||
|
@@ -150,11 +109,11 @@ _IO_fwide (FILE *fp, int mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static enum __codecvt_result
|
||||||
|
-do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
- const wchar_t *from_start, const wchar_t *from_end,
|
||||||
|
- const wchar_t **from_stop, char *to_start, char *to_end,
|
||||||
|
- char **to_stop)
|
||||||
|
+enum __codecvt_result
|
||||||
|
+__libio_codecvt_out (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
+ const wchar_t *from_start, const wchar_t *from_end,
|
||||||
|
+ const wchar_t **from_stop, char *to_start, char *to_end,
|
||||||
|
+ char **to_stop)
|
||||||
|
{
|
||||||
|
enum __codecvt_result result;
|
||||||
|
|
||||||
|
@@ -202,57 +161,11 @@ do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static enum __codecvt_result
|
||||||
|
-do_unshift (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
- char *to_start, char *to_end, char **to_stop)
|
||||||
|
-{
|
||||||
|
- enum __codecvt_result result;
|
||||||
|
-
|
||||||
|
- struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps;
|
||||||
|
- int status;
|
||||||
|
- size_t dummy;
|
||||||
|
-
|
||||||
|
- codecvt->__cd_out.__cd.__data[0].__outbuf = (unsigned char *) to_start;
|
||||||
|
- codecvt->__cd_out.__cd.__data[0].__outbufend = (unsigned char *) to_end;
|
||||||
|
- codecvt->__cd_out.__cd.__data[0].__statep = statep;
|
||||||
|
-
|
||||||
|
- __gconv_fct fct = gs->__fct;
|
||||||
|
-#ifdef PTR_DEMANGLE
|
||||||
|
- if (gs->__shlib_handle != NULL)
|
||||||
|
- PTR_DEMANGLE (fct);
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
- status = DL_CALL_FCT (fct,
|
||||||
|
- (gs, codecvt->__cd_out.__cd.__data, NULL, NULL,
|
||||||
|
- NULL, &dummy, 1, 0));
|
||||||
|
-
|
||||||
|
- *to_stop = (char *) codecvt->__cd_out.__cd.__data[0].__outbuf;
|
||||||
|
-
|
||||||
|
- switch (status)
|
||||||
|
- {
|
||||||
|
- case __GCONV_OK:
|
||||||
|
- case __GCONV_EMPTY_INPUT:
|
||||||
|
- result = __codecvt_ok;
|
||||||
|
- break;
|
||||||
|
-
|
||||||
|
- case __GCONV_FULL_OUTPUT:
|
||||||
|
- case __GCONV_INCOMPLETE_INPUT:
|
||||||
|
- result = __codecvt_partial;
|
||||||
|
- break;
|
||||||
|
-
|
||||||
|
- default:
|
||||||
|
- result = __codecvt_error;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return result;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static enum __codecvt_result
|
||||||
|
-do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
- const char *from_start, const char *from_end, const char **from_stop,
|
||||||
|
- wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop)
|
||||||
|
+enum __codecvt_result
|
||||||
|
+__libio_codecvt_in (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
+ const char *from_start, const char *from_end,
|
||||||
|
+ const char **from_stop,
|
||||||
|
+ wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop)
|
||||||
|
{
|
||||||
|
enum __codecvt_result result;
|
||||||
|
|
||||||
|
@@ -300,8 +213,8 @@ do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-do_encoding (struct _IO_codecvt *codecvt)
|
||||||
|
+int
|
||||||
|
+__libio_codecvt_encoding (struct _IO_codecvt *codecvt)
|
||||||
|
{
|
||||||
|
/* See whether the encoding is stateful. */
|
||||||
|
if (codecvt->__cd_in.__cd.__steps[0].__stateful)
|
||||||
|
@@ -317,16 +230,10 @@ do_encoding (struct _IO_codecvt *codecvt)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-do_always_noconv (struct _IO_codecvt *codecvt)
|
||||||
|
-{
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static int
|
||||||
|
-do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
- const char *from_start, const char *from_end, size_t max)
|
||||||
|
+int
|
||||||
|
+__libio_codecvt_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
+ const char *from_start, const char *from_end,
|
||||||
|
+ size_t max)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
const unsigned char *cp = (const unsigned char *) from_start;
|
||||||
|
@@ -353,10 +260,3 @@ do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static int
|
||||||
|
-do_max_length (struct _IO_codecvt *codecvt)
|
||||||
|
-{
|
||||||
|
- return codecvt->__cd_in.__cd.__steps[0].__max_needed_from;
|
||||||
|
-}
|
||||||
|
diff --git a/libio/libio.h b/libio/libio.h
|
||||||
|
index c38095ff77..b985c386a2 100644
|
||||||
|
--- a/libio/libio.h
|
||||||
|
+++ b/libio/libio.h
|
||||||
|
@@ -116,40 +116,8 @@ struct _IO_marker {
|
||||||
|
int _pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
-/* This is the structure from the libstdc++ codecvt class. */
|
||||||
|
-enum __codecvt_result
|
||||||
|
-{
|
||||||
|
- __codecvt_ok,
|
||||||
|
- __codecvt_partial,
|
||||||
|
- __codecvt_error,
|
||||||
|
- __codecvt_noconv
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-/* The order of the elements in the following struct must match the order
|
||||||
|
- of the virtual functions in the libstdc++ codecvt class. */
|
||||||
|
struct _IO_codecvt
|
||||||
|
{
|
||||||
|
- void (*__codecvt_destr) (struct _IO_codecvt *);
|
||||||
|
- enum __codecvt_result (*__codecvt_do_out) (struct _IO_codecvt *,
|
||||||
|
- __mbstate_t *,
|
||||||
|
- const wchar_t *,
|
||||||
|
- const wchar_t *,
|
||||||
|
- const wchar_t **, char *,
|
||||||
|
- char *, char **);
|
||||||
|
- enum __codecvt_result (*__codecvt_do_unshift) (struct _IO_codecvt *,
|
||||||
|
- __mbstate_t *, char *,
|
||||||
|
- char *, char **);
|
||||||
|
- enum __codecvt_result (*__codecvt_do_in) (struct _IO_codecvt *,
|
||||||
|
- __mbstate_t *,
|
||||||
|
- const char *, const char *,
|
||||||
|
- const char **, wchar_t *,
|
||||||
|
- wchar_t *, wchar_t **);
|
||||||
|
- int (*__codecvt_do_encoding) (struct _IO_codecvt *);
|
||||||
|
- int (*__codecvt_do_always_noconv) (struct _IO_codecvt *);
|
||||||
|
- int (*__codecvt_do_length) (struct _IO_codecvt *, __mbstate_t *,
|
||||||
|
- const char *, const char *, size_t);
|
||||||
|
- int (*__codecvt_do_max_length) (struct _IO_codecvt *);
|
||||||
|
-
|
||||||
|
_IO_iconv_t __cd_in;
|
||||||
|
_IO_iconv_t __cd_out;
|
||||||
|
};
|
||||||
|
diff --git a/libio/libioP.h b/libio/libioP.h
|
||||||
|
index 7bdec86a62..66afaa8968 100644
|
||||||
|
--- a/libio/libioP.h
|
||||||
|
+++ b/libio/libioP.h
|
||||||
|
@@ -476,7 +476,6 @@ extern const struct _IO_jump_t _IO_streambuf_jumps;
|
||||||
|
extern const struct _IO_jump_t _IO_old_proc_jumps attribute_hidden;
|
||||||
|
extern const struct _IO_jump_t _IO_str_jumps attribute_hidden;
|
||||||
|
extern const struct _IO_jump_t _IO_wstr_jumps attribute_hidden;
|
||||||
|
-extern const struct _IO_codecvt __libio_codecvt attribute_hidden;
|
||||||
|
extern int _IO_do_write (FILE *, const char *, size_t);
|
||||||
|
libc_hidden_proto (_IO_do_write)
|
||||||
|
extern int _IO_new_do_write (FILE *, const char *, size_t);
|
||||||
|
@@ -932,4 +931,32 @@ IO_validate_vtable (const struct _IO_jump_t *vtable)
|
||||||
|
return vtable;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Character set conversion. */
|
||||||
|
+
|
||||||
|
+enum __codecvt_result
|
||||||
|
+{
|
||||||
|
+ __codecvt_ok,
|
||||||
|
+ __codecvt_partial,
|
||||||
|
+ __codecvt_error,
|
||||||
|
+ __codecvt_noconv
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+enum __codecvt_result __libio_codecvt_out (struct _IO_codecvt *,
|
||||||
|
+ __mbstate_t *,
|
||||||
|
+ const wchar_t *,
|
||||||
|
+ const wchar_t *,
|
||||||
|
+ const wchar_t **, char *,
|
||||||
|
+ char *, char **)
|
||||||
|
+ attribute_hidden;
|
||||||
|
+enum __codecvt_result __libio_codecvt_in (struct _IO_codecvt *,
|
||||||
|
+ __mbstate_t *,
|
||||||
|
+ const char *, const char *,
|
||||||
|
+ const char **, wchar_t *,
|
||||||
|
+ wchar_t *, wchar_t **)
|
||||||
|
+ attribute_hidden;
|
||||||
|
+int __libio_codecvt_encoding (struct _IO_codecvt *) attribute_hidden;
|
||||||
|
+int __libio_codecvt_length (struct _IO_codecvt *, __mbstate_t *,
|
||||||
|
+ const char *, const char *, size_t)
|
||||||
|
+ attribute_hidden;
|
||||||
|
+
|
||||||
|
#endif /* libioP.h. */
|
||||||
|
diff --git a/libio/wfileops.c b/libio/wfileops.c
|
||||||
|
index 69fbb62a02..f1863db638 100644
|
||||||
|
--- a/libio/wfileops.c
|
||||||
|
+++ b/libio/wfileops.c
|
||||||
|
@@ -72,11 +72,11 @@ _IO_wdo_write (FILE *fp, const wchar_t *data, size_t to_do)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now convert from the internal format into the external buffer. */
|
||||||
|
- result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state,
|
||||||
|
- data, data + to_do, &new_data,
|
||||||
|
- write_ptr,
|
||||||
|
- buf_end,
|
||||||
|
- &write_ptr);
|
||||||
|
+ result = __libio_codecvt_out (cc, &fp->_wide_data->_IO_state,
|
||||||
|
+ data, data + to_do, &new_data,
|
||||||
|
+ write_ptr,
|
||||||
|
+ buf_end,
|
||||||
|
+ &write_ptr);
|
||||||
|
|
||||||
|
/* Write out what we produced so far. */
|
||||||
|
if (_IO_new_do_write (fp, write_base, write_ptr - write_base) == EOF)
|
||||||
|
@@ -140,12 +140,12 @@ _IO_wfile_underflow (FILE *fp)
|
||||||
|
fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
|
||||||
|
fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
|
||||||
|
fp->_wide_data->_IO_buf_base;
|
||||||
|
- status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
|
||||||
|
- fp->_IO_read_ptr, fp->_IO_read_end,
|
||||||
|
- &read_stop,
|
||||||
|
- fp->_wide_data->_IO_read_ptr,
|
||||||
|
- fp->_wide_data->_IO_buf_end,
|
||||||
|
- &fp->_wide_data->_IO_read_end);
|
||||||
|
+ status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
|
||||||
|
+ fp->_IO_read_ptr, fp->_IO_read_end,
|
||||||
|
+ &read_stop,
|
||||||
|
+ fp->_wide_data->_IO_read_ptr,
|
||||||
|
+ fp->_wide_data->_IO_buf_end,
|
||||||
|
+ &fp->_wide_data->_IO_read_end);
|
||||||
|
|
||||||
|
fp->_IO_read_base = fp->_IO_read_ptr;
|
||||||
|
fp->_IO_read_ptr = (char *) read_stop;
|
||||||
|
@@ -266,11 +266,11 @@ _IO_wfile_underflow (FILE *fp)
|
||||||
|
naccbuf += to_copy;
|
||||||
|
from = accbuf;
|
||||||
|
}
|
||||||
|
- status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
|
||||||
|
- from, to, &read_ptr_copy,
|
||||||
|
- fp->_wide_data->_IO_read_end,
|
||||||
|
- fp->_wide_data->_IO_buf_end,
|
||||||
|
- &fp->_wide_data->_IO_read_end);
|
||||||
|
+ status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
|
||||||
|
+ from, to, &read_ptr_copy,
|
||||||
|
+ fp->_wide_data->_IO_read_end,
|
||||||
|
+ fp->_wide_data->_IO_buf_end,
|
||||||
|
+ &fp->_wide_data->_IO_read_end);
|
||||||
|
|
||||||
|
if (__glibc_unlikely (naccbuf != 0))
|
||||||
|
fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]);
|
||||||
|
@@ -372,12 +372,12 @@ _IO_wfile_underflow_mmap (FILE *fp)
|
||||||
|
fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
|
||||||
|
fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
|
||||||
|
fp->_wide_data->_IO_buf_base;
|
||||||
|
- (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
|
||||||
|
- fp->_IO_read_ptr, fp->_IO_read_end,
|
||||||
|
- &read_stop,
|
||||||
|
- fp->_wide_data->_IO_read_ptr,
|
||||||
|
- fp->_wide_data->_IO_buf_end,
|
||||||
|
- &fp->_wide_data->_IO_read_end);
|
||||||
|
+ __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
|
||||||
|
+ fp->_IO_read_ptr, fp->_IO_read_end,
|
||||||
|
+ &read_stop,
|
||||||
|
+ fp->_wide_data->_IO_read_ptr,
|
||||||
|
+ fp->_wide_data->_IO_buf_end,
|
||||||
|
+ &fp->_wide_data->_IO_read_end);
|
||||||
|
|
||||||
|
fp->_IO_read_ptr = (char *) read_stop;
|
||||||
|
|
||||||
|
@@ -495,7 +495,7 @@ _IO_wfile_sync (FILE *fp)
|
||||||
|
struct _IO_codecvt *cv = fp->_codecvt;
|
||||||
|
off64_t new_pos;
|
||||||
|
|
||||||
|
- int clen = (*cv->__codecvt_do_encoding) (cv);
|
||||||
|
+ int clen = __libio_codecvt_encoding (cv);
|
||||||
|
|
||||||
|
if (clen > 0)
|
||||||
|
/* It is easy, a fixed number of input bytes are used for each
|
||||||
|
@@ -511,9 +511,9 @@ _IO_wfile_sync (FILE *fp)
|
||||||
|
size_t wnread = (fp->_wide_data->_IO_read_ptr
|
||||||
|
- fp->_wide_data->_IO_read_base);
|
||||||
|
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
|
||||||
|
- nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
|
||||||
|
- fp->_IO_read_base,
|
||||||
|
- fp->_IO_read_end, wnread);
|
||||||
|
+ nread = __libio_codecvt_length (cv, &fp->_wide_data->_IO_state,
|
||||||
|
+ fp->_IO_read_base,
|
||||||
|
+ fp->_IO_read_end, wnread);
|
||||||
|
fp->_IO_read_ptr = fp->_IO_read_base + nread;
|
||||||
|
delta = -(fp->_IO_read_end - fp->_IO_read_base - nread);
|
||||||
|
}
|
||||||
|
@@ -548,7 +548,7 @@ adjust_wide_data (FILE *fp, bool do_convert)
|
||||||
|
{
|
||||||
|
struct _IO_codecvt *cv = fp->_codecvt;
|
||||||
|
|
||||||
|
- int clen = (*cv->__codecvt_do_encoding) (cv);
|
||||||
|
+ int clen = __libio_codecvt_encoding (cv);
|
||||||
|
|
||||||
|
/* Take the easy way out for constant length encodings if we don't need to
|
||||||
|
convert. */
|
||||||
|
@@ -565,12 +565,12 @@ adjust_wide_data (FILE *fp, bool do_convert)
|
||||||
|
{
|
||||||
|
|
||||||
|
fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
|
||||||
|
- status = (*cv->__codecvt_do_in) (cv, &fp->_wide_data->_IO_state,
|
||||||
|
- fp->_IO_read_base, fp->_IO_read_ptr,
|
||||||
|
- &read_stop,
|
||||||
|
- fp->_wide_data->_IO_read_base,
|
||||||
|
- fp->_wide_data->_IO_buf_end,
|
||||||
|
- &fp->_wide_data->_IO_read_end);
|
||||||
|
+ status = __libio_codecvt_in (cv, &fp->_wide_data->_IO_state,
|
||||||
|
+ fp->_IO_read_base, fp->_IO_read_ptr,
|
||||||
|
+ &read_stop,
|
||||||
|
+ fp->_wide_data->_IO_read_base,
|
||||||
|
+ fp->_wide_data->_IO_buf_end,
|
||||||
|
+ &fp->_wide_data->_IO_read_end);
|
||||||
|
|
||||||
|
/* Should we return EILSEQ? */
|
||||||
|
if (__glibc_unlikely (status == __codecvt_error))
|
||||||
|
@@ -648,7 +648,7 @@ do_ftell_wide (FILE *fp)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _IO_codecvt *cv = fp->_codecvt;
|
||||||
|
- int clen = (*cv->__codecvt_do_encoding) (cv);
|
||||||
|
+ int clen = __libio_codecvt_encoding (cv);
|
||||||
|
|
||||||
|
if (!unflushed_writes)
|
||||||
|
{
|
||||||
|
@@ -663,9 +663,9 @@ do_ftell_wide (FILE *fp)
|
||||||
|
|
||||||
|
size_t delta = wide_read_ptr - wide_read_base;
|
||||||
|
__mbstate_t state = fp->_wide_data->_IO_last_state;
|
||||||
|
- nread = (*cv->__codecvt_do_length) (cv, &state,
|
||||||
|
- fp->_IO_read_base,
|
||||||
|
- fp->_IO_read_end, delta);
|
||||||
|
+ nread = __libio_codecvt_length (cv, &state,
|
||||||
|
+ fp->_IO_read_base,
|
||||||
|
+ fp->_IO_read_end, delta);
|
||||||
|
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -688,9 +688,8 @@ do_ftell_wide (FILE *fp)
|
||||||
|
enum __codecvt_result status;
|
||||||
|
|
||||||
|
__mbstate_t state = fp->_wide_data->_IO_last_state;
|
||||||
|
- status = (*cv->__codecvt_do_out) (cv, &state,
|
||||||
|
- in, in + delta, &in,
|
||||||
|
- out, out + outsize, &outstop);
|
||||||
|
+ status = __libio_codecvt_out (cv, &state, in, in + delta, &in,
|
||||||
|
+ out, out + outsize, &outstop);
|
||||||
|
|
||||||
|
/* We don't check for __codecvt_partial because it can be
|
||||||
|
returned on one of two conditions: either the output
|
||||||
|
@@ -801,7 +800,7 @@ _IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode)
|
||||||
|
find out which position in the external buffer corresponds to
|
||||||
|
the current position in the internal buffer. */
|
||||||
|
cv = fp->_codecvt;
|
||||||
|
- clen = (*cv->__codecvt_do_encoding) (cv);
|
||||||
|
+ clen = __libio_codecvt_encoding (cv);
|
||||||
|
|
||||||
|
if (mode != 0 || !was_writing)
|
||||||
|
{
|
||||||
|
@@ -819,10 +818,10 @@ _IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode)
|
||||||
|
delta = (fp->_wide_data->_IO_read_ptr
|
||||||
|
- fp->_wide_data->_IO_read_base);
|
||||||
|
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
|
||||||
|
- nread = (*cv->__codecvt_do_length) (cv,
|
||||||
|
- &fp->_wide_data->_IO_state,
|
||||||
|
- fp->_IO_read_base,
|
||||||
|
- fp->_IO_read_end, delta);
|
||||||
|
+ nread = __libio_codecvt_length (cv,
|
||||||
|
+ &fp->_wide_data->_IO_state,
|
||||||
|
+ fp->_IO_read_base,
|
||||||
|
+ fp->_IO_read_end, delta);
|
||||||
|
fp->_IO_read_ptr = fp->_IO_read_base + nread;
|
||||||
|
fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr;
|
||||||
|
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
|
81
SOURCES/glibc-rh1764242.patch
Normal file
81
SOURCES/glibc-rh1764242.patch
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
commit 4997e8f31e7415652c3dedec672c0e9bf8caa9ca
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Fri Feb 1 10:39:57 2019 -0200
|
||||||
|
|
||||||
|
math: Enable some math builtins for clang
|
||||||
|
|
||||||
|
This patch enable the builtin usage for clang for the C99 functions
|
||||||
|
fpclassify, isfinite, isnormal, isnan, isinf, and sigbit. This allows
|
||||||
|
clang optimize the calls on frontend instead of call the appropriate
|
||||||
|
glibc symbols.
|
||||||
|
|
||||||
|
Checked on aarch64-linux-gnu and x86_64-linux-gnu. I checked the supported
|
||||||
|
version for each builtin based on released version from clang/llvm.
|
||||||
|
|
||||||
|
* math/math.h (fpclassify, isfinite, isnormal, isnan): Use builtin for
|
||||||
|
clang 2.8.
|
||||||
|
(signbit): Use builtin for clang 3.3.
|
||||||
|
(isinf): Use builtin for clang 3.7.
|
||||||
|
|
||||||
|
diff --git a/math/math.h b/math/math.h
|
||||||
|
index ddee4e408389722f..b3b414f3678e91f7 100644
|
||||||
|
--- a/math/math.h
|
||||||
|
+++ b/math/math.h
|
||||||
|
@@ -874,7 +874,8 @@ enum
|
||||||
|
the __SUPPORT_SNAN__ check may be skipped for those versions. */
|
||||||
|
|
||||||
|
/* Return number of classification appropriate for X. */
|
||||||
|
-# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ \
|
||||||
|
+# if ((__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \
|
||||||
|
+ || __glibc_clang_prereq (2,8)) \
|
||||||
|
&& (!defined __OPTIMIZE_SIZE__ || defined __cplusplus)
|
||||||
|
/* The check for __cplusplus allows the use of the builtin, even
|
||||||
|
when optimization for size is on. This is provided for
|
||||||
|
@@ -889,7 +890,7 @@ enum
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Return nonzero value if sign of X is negative. */
|
||||||
|
-# if __GNUC_PREREQ (6,0)
|
||||||
|
+# if __GNUC_PREREQ (6,0) || __glibc_clang_prereq (3,3)
|
||||||
|
# define signbit(x) __builtin_signbit (x)
|
||||||
|
# elif defined __cplusplus
|
||||||
|
/* In C++ mode, __MATH_TG cannot be used, because it relies on
|
||||||
|
@@ -907,14 +908,16 @@ enum
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Return nonzero value if X is not +-Inf or NaN. */
|
||||||
|
-# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
|
||||||
|
+# if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \
|
||||||
|
+ || __glibc_clang_prereq (2,8)
|
||||||
|
# define isfinite(x) __builtin_isfinite (x)
|
||||||
|
# else
|
||||||
|
# define isfinite(x) __MATH_TG ((x), __finite, (x))
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Return nonzero value if X is neither zero, subnormal, Inf, nor NaN. */
|
||||||
|
-# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
|
||||||
|
+# if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \
|
||||||
|
+ || __glibc_clang_prereq (2,8)
|
||||||
|
# define isnormal(x) __builtin_isnormal (x)
|
||||||
|
# else
|
||||||
|
# define isnormal(x) (fpclassify (x) == FP_NORMAL)
|
||||||
|
@@ -922,7 +925,8 @@ enum
|
||||||
|
|
||||||
|
/* Return nonzero value if X is a NaN. We could use `fpclassify' but
|
||||||
|
we already have this functions `__isnan' and it is faster. */
|
||||||
|
-# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
|
||||||
|
+# if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \
|
||||||
|
+ || __glibc_clang_prereq (2,8)
|
||||||
|
# define isnan(x) __builtin_isnan (x)
|
||||||
|
# else
|
||||||
|
# define isnan(x) __MATH_TG ((x), __isnan, (x))
|
||||||
|
@@ -939,7 +943,8 @@ enum
|
||||||
|
# define isinf(x) \
|
||||||
|
(__builtin_types_compatible_p (__typeof (x), _Float128) \
|
||||||
|
? __isinff128 (x) : __builtin_isinf_sign (x))
|
||||||
|
-# elif __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
|
||||||
|
+# elif (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \
|
||||||
|
+ || __glibc_clang_prereq (3,7)
|
||||||
|
# define isinf(x) __builtin_isinf_sign (x)
|
||||||
|
# else
|
||||||
|
# define isinf(x) __MATH_TG ((x), __isinf, (x))
|
740
SOURCES/glibc-rh1769304.patch
Normal file
740
SOURCES/glibc-rh1769304.patch
Normal file
@ -0,0 +1,740 @@
|
|||||||
|
commit 711a322a235d4c8177713f11aa59156603b94aeb
|
||||||
|
Author: Zack Weinberg <zackw@panix.com>
|
||||||
|
Date: Mon Mar 11 10:59:27 2019 -0400
|
||||||
|
|
||||||
|
Use a proper C tokenizer to implement the obsolete typedefs test.
|
||||||
|
|
||||||
|
The test for obsolete typedefs in installed headers was implemented
|
||||||
|
using grep, and could therefore get false positives on e.g. “ulong”
|
||||||
|
in a comment. It was also scanning all of the headers included by
|
||||||
|
our headers, and therefore testing headers we don’t control, e.g.
|
||||||
|
Linux kernel headers.
|
||||||
|
|
||||||
|
This patch splits the obsolete-typedef test from
|
||||||
|
scripts/check-installed-headers.sh to a separate program,
|
||||||
|
scripts/check-obsolete-constructs.py. Being implemented in Python,
|
||||||
|
it is feasible to make it tokenize C accurately enough to avoid false
|
||||||
|
positives on the contents of comments and strings. It also only
|
||||||
|
examines $(headers) in each subdirectory--all the headers we install,
|
||||||
|
but not any external dependencies of those headers. Headers whose
|
||||||
|
installed name starts with finclude/ are ignored, on the assumption
|
||||||
|
that they contain Fortran.
|
||||||
|
|
||||||
|
It is also feasible to make the new test understand the difference
|
||||||
|
between _defining_ the obsolete typedefs and _using_ the obsolete
|
||||||
|
typedefs, which means posix/{bits,sys}/types.h no longer need to be
|
||||||
|
exempted. This uncovered an actual bug in bits/types.h: __quad_t and
|
||||||
|
__u_quad_t were being used to define __S64_TYPE, __U64_TYPE,
|
||||||
|
__SQUAD_TYPE and __UQUAD_TYPE. These are changed to __int64_t and
|
||||||
|
__uint64_t respectively. This is a safe change, despite the comments
|
||||||
|
in bits/types.h claiming a difference between __quad_t and __int64_t,
|
||||||
|
because those comments are incorrect. In all current ABIs, both
|
||||||
|
__quad_t and __int64_t are ‘long’ when ‘long’ is a 64-bit type, and
|
||||||
|
‘long long’ when ‘long’ is a 32-bit type, and similarly for __u_quad_t
|
||||||
|
and __uint64_t. (Changing the types to be what the comments say they
|
||||||
|
are would be an ABI break, as it affects C++ name mangling.) This
|
||||||
|
patch includes a minimal change to make the comments not completely
|
||||||
|
wrong.
|
||||||
|
|
||||||
|
sys/types.h was defining the legacy BSD u_intN_t typedefs using a
|
||||||
|
construct that was not necessarily consistent with how the C99 uintN_t
|
||||||
|
typedefs are defined, and is also too complicated for the new script to
|
||||||
|
understand (it lexes C relatively accurately, but it does not attempt
|
||||||
|
to expand preprocessor macros, nor does it do any actual parsing).
|
||||||
|
This patch cuts all of that out and uses bits/types.h's __uintN_t typedefs
|
||||||
|
to define u_intN_t instead. This is verified to not change the ABI on
|
||||||
|
any supported architecture, via the c++-types test, which means u_intN_t
|
||||||
|
and uintN_t were, in fact, consistent on all supported architectures.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
* scripts/check-obsolete-constructs.py: New test script.
|
||||||
|
* scripts/check-installed-headers.sh: Remove tests for
|
||||||
|
obsolete typedefs, superseded by check-obsolete-constructs.py.
|
||||||
|
* Rules: Run scripts/check-obsolete-constructs.py over $(headers)
|
||||||
|
as a special test. Update commentary.
|
||||||
|
* posix/bits/types.h (__SQUAD_TYPE, __S64_TYPE): Define as __int64_t.
|
||||||
|
(__UQUAD_TYPE, __U64_TYPE): Define as __uint64_t.
|
||||||
|
Update commentary.
|
||||||
|
* posix/sys/types.h (__u_intN_t): Remove.
|
||||||
|
(u_int8_t): Typedef using __uint8_t.
|
||||||
|
(u_int16_t): Typedef using __uint16_t.
|
||||||
|
(u_int32_t): Typedef using __uint32_t.
|
||||||
|
(u_int64_t): Typedef using __uint64_t.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
Rules
|
||||||
|
(textual conflicts due to lack of check-wrapper-headers test.)
|
||||||
|
|
||||||
|
diff --git a/Rules b/Rules
|
||||||
|
index 5abb7270aa8e24aa..a07dbb8d978b5769 100644
|
||||||
|
--- a/Rules
|
||||||
|
+++ b/Rules
|
||||||
|
@@ -82,7 +82,8 @@ $(common-objpfx)dummy.c:
|
||||||
|
common-generated += dummy.o dummy.c
|
||||||
|
|
||||||
|
ifneq "$(headers)" ""
|
||||||
|
-# Special test of all the installed headers in this directory.
|
||||||
|
+# Test that all of the headers installed by this directory can be compiled
|
||||||
|
+# in isolation.
|
||||||
|
tests-special += $(objpfx)check-installed-headers-c.out
|
||||||
|
libof-check-installed-headers-c := testsuite
|
||||||
|
$(objpfx)check-installed-headers-c.out: \
|
||||||
|
@@ -93,6 +94,8 @@ $(objpfx)check-installed-headers-c.out: \
|
||||||
|
$(evaluate-test)
|
||||||
|
|
||||||
|
ifneq "$(CXX)" ""
|
||||||
|
+# If a C++ compiler is available, also test that they can be compiled
|
||||||
|
+# in isolation as C++.
|
||||||
|
tests-special += $(objpfx)check-installed-headers-cxx.out
|
||||||
|
libof-check-installed-headers-cxx := testsuite
|
||||||
|
$(objpfx)check-installed-headers-cxx.out: \
|
||||||
|
@@ -101,8 +104,19 @@ $(objpfx)check-installed-headers-cxx.out: \
|
||||||
|
"$(CXX) $(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
|
||||||
|
$(headers) > $@; \
|
||||||
|
$(evaluate-test)
|
||||||
|
-endif
|
||||||
|
-endif
|
||||||
|
+endif # $(CXX)
|
||||||
|
+
|
||||||
|
+# Test that none of the headers installed by this directory use certain
|
||||||
|
+# obsolete constructs (e.g. legacy BSD typedefs superseded by stdint.h).
|
||||||
|
+# This script does not need $(py-env).
|
||||||
|
+tests-special += $(objpfx)check-obsolete-constructs.out
|
||||||
|
+libof-check-obsolete-constructs := testsuite
|
||||||
|
+$(objpfx)check-obsolete-constructs.out: \
|
||||||
|
+ $(..)scripts/check-obsolete-constructs.py $(headers)
|
||||||
|
+ $(PYTHON) $^ > $@ 2>&1; \
|
||||||
|
+ $(evaluate-test)
|
||||||
|
+
|
||||||
|
+endif # $(headers)
|
||||||
|
|
||||||
|
# This makes all the auxiliary and test programs.
|
||||||
|
|
||||||
|
diff --git a/posix/bits/types.h b/posix/bits/types.h
|
||||||
|
index 5e22ce41bf4c29b3..64f344c6e7897491 100644
|
||||||
|
--- a/posix/bits/types.h
|
||||||
|
+++ b/posix/bits/types.h
|
||||||
|
@@ -86,7 +86,7 @@ __extension__ typedef unsigned long long int __uintmax_t;
|
||||||
|
32 -- "natural" 32-bit type (always int)
|
||||||
|
64 -- "natural" 64-bit type (long or long long)
|
||||||
|
LONG32 -- 32-bit type, traditionally long
|
||||||
|
- QUAD -- 64-bit type, always long long
|
||||||
|
+ QUAD -- 64-bit type, traditionally long long
|
||||||
|
WORD -- natural type of __WORDSIZE bits (int or long)
|
||||||
|
LONGWORD -- type of __WORDSIZE bits, traditionally long
|
||||||
|
|
||||||
|
@@ -112,14 +112,14 @@ __extension__ typedef unsigned long long int __uintmax_t;
|
||||||
|
#define __SLONGWORD_TYPE long int
|
||||||
|
#define __ULONGWORD_TYPE unsigned long int
|
||||||
|
#if __WORDSIZE == 32
|
||||||
|
-# define __SQUAD_TYPE __quad_t
|
||||||
|
-# define __UQUAD_TYPE __u_quad_t
|
||||||
|
+# define __SQUAD_TYPE __int64_t
|
||||||
|
+# define __UQUAD_TYPE __uint64_t
|
||||||
|
# define __SWORD_TYPE int
|
||||||
|
# define __UWORD_TYPE unsigned int
|
||||||
|
# define __SLONG32_TYPE long int
|
||||||
|
# define __ULONG32_TYPE unsigned long int
|
||||||
|
-# define __S64_TYPE __quad_t
|
||||||
|
-# define __U64_TYPE __u_quad_t
|
||||||
|
+# define __S64_TYPE __int64_t
|
||||||
|
+# define __U64_TYPE __uint64_t
|
||||||
|
/* We want __extension__ before typedef's that use nonstandard base types
|
||||||
|
such as `long long' in C89 mode. */
|
||||||
|
# define __STD_TYPE __extension__ typedef
|
||||||
|
diff --git a/posix/sys/types.h b/posix/sys/types.h
|
||||||
|
index db524d6cd13f0379..47eff1a7b1a91c81 100644
|
||||||
|
--- a/posix/sys/types.h
|
||||||
|
+++ b/posix/sys/types.h
|
||||||
|
@@ -154,37 +154,20 @@ typedef unsigned int uint;
|
||||||
|
|
||||||
|
#include <bits/stdint-intn.h>
|
||||||
|
|
||||||
|
-#if !__GNUC_PREREQ (2, 7)
|
||||||
|
-
|
||||||
|
/* These were defined by ISO C without the first `_'. */
|
||||||
|
-typedef unsigned char u_int8_t;
|
||||||
|
-typedef unsigned short int u_int16_t;
|
||||||
|
-typedef unsigned int u_int32_t;
|
||||||
|
-# if __WORDSIZE == 64
|
||||||
|
-typedef unsigned long int u_int64_t;
|
||||||
|
-# else
|
||||||
|
-__extension__ typedef unsigned long long int u_int64_t;
|
||||||
|
-# endif
|
||||||
|
-
|
||||||
|
-typedef int register_t;
|
||||||
|
-
|
||||||
|
-#else
|
||||||
|
-
|
||||||
|
-/* For GCC 2.7 and later, we can use specific type-size attributes. */
|
||||||
|
-# define __u_intN_t(N, MODE) \
|
||||||
|
- typedef unsigned int u_int##N##_t __attribute__ ((__mode__ (MODE)))
|
||||||
|
-
|
||||||
|
-__u_intN_t (8, __QI__);
|
||||||
|
-__u_intN_t (16, __HI__);
|
||||||
|
-__u_intN_t (32, __SI__);
|
||||||
|
-__u_intN_t (64, __DI__);
|
||||||
|
+typedef __uint8_t u_int8_t;
|
||||||
|
+typedef __uint16_t u_int16_t;
|
||||||
|
+typedef __uint32_t u_int32_t;
|
||||||
|
+typedef __uint64_t u_int64_t;
|
||||||
|
|
||||||
|
+#if __GNUC_PREREQ (2, 7)
|
||||||
|
typedef int register_t __attribute__ ((__mode__ (__word__)));
|
||||||
|
-
|
||||||
|
+#else
|
||||||
|
+typedef int register_t;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* Some code from BIND tests this macro to see if the types above are
|
||||||
|
defined. */
|
||||||
|
-#endif
|
||||||
|
#define __BIT_TYPES_DEFINED__ 1
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/scripts/check-installed-headers.sh b/scripts/check-installed-headers.sh
|
||||||
|
index 7a1969b43a144ebb..c2aeea5aabcc7ffd 100644
|
||||||
|
--- a/scripts/check-installed-headers.sh
|
||||||
|
+++ b/scripts/check-installed-headers.sh
|
||||||
|
@@ -16,11 +16,9 @@
|
||||||
|
# License along with the GNU C Library; if not, see
|
||||||
|
# <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-# Check installed headers for cleanliness. For each header, confirm
|
||||||
|
-# that it's possible to compile a file that includes that header and
|
||||||
|
-# does nothing else, in several different compilation modes. Also,
|
||||||
|
-# scan the header for a set of obsolete typedefs that should no longer
|
||||||
|
-# appear.
|
||||||
|
+# For each installed header, confirm that it's possible to compile a
|
||||||
|
+# file that includes that header and does nothing else, in several
|
||||||
|
+# different compilation modes.
|
||||||
|
|
||||||
|
# These compilation switches assume GCC or compatible, which is probably
|
||||||
|
# fine since we also assume that when _building_ glibc.
|
||||||
|
@@ -31,13 +29,6 @@ cxx_modes="-std=c++98 -std=gnu++98 -std=c++11 -std=gnu++11"
|
||||||
|
# These are probably the most commonly used three.
|
||||||
|
lib_modes="-D_DEFAULT_SOURCE=1 -D_GNU_SOURCE=1 -D_XOPEN_SOURCE=700"
|
||||||
|
|
||||||
|
-# sys/types.h+bits/types.h have to define the obsolete types.
|
||||||
|
-# rpc(svc)/* have the obsolete types too deeply embedded in their API
|
||||||
|
-# to remove.
|
||||||
|
-skip_obsolete_type_check='*/sys/types.h|*/bits/types.h|*/rpc/*|*/rpcsvc/*'
|
||||||
|
-obsolete_type_re=\
|
||||||
|
-'\<((__)?(quad_t|u(short|int|long|_(char|short|int([0-9]+_t)?|long|quad_t))))\>'
|
||||||
|
-
|
||||||
|
if [ $# -lt 3 ]; then
|
||||||
|
echo "usage: $0 c|c++ \"compile command\" header header header..." >&2
|
||||||
|
exit 2
|
||||||
|
@@ -46,14 +37,10 @@ case "$1" in
|
||||||
|
(c)
|
||||||
|
lang_modes="$c_modes"
|
||||||
|
cih_test_c=$(mktemp ${TMPDIR-/tmp}/cih_test_XXXXXX.c)
|
||||||
|
- already="$skip_obsolete_type_check"
|
||||||
|
;;
|
||||||
|
(c++)
|
||||||
|
lang_modes="$cxx_modes"
|
||||||
|
cih_test_c=$(mktemp ${TMPDIR-/tmp}/cih_test_XXXXXX.cc)
|
||||||
|
- # The obsolete-type check can be skipped for C++; it is
|
||||||
|
- # sufficient to do it for C.
|
||||||
|
- already="*"
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
echo "usage: $0 c|c++ \"compile command\" header header header..." >&2
|
||||||
|
@@ -155,22 +142,8 @@ $expanded_lib_mode
|
||||||
|
int avoid_empty_translation_unit;
|
||||||
|
EOF
|
||||||
|
if $cc_cmd -fsyntax-only $lang_mode "$cih_test_c" 2>&1
|
||||||
|
- then
|
||||||
|
- includes=$($cc_cmd -fsyntax-only -H $lang_mode \
|
||||||
|
- "$cih_test_c" 2>&1 | sed -ne 's/^[.][.]* //p')
|
||||||
|
- for h in $includes; do
|
||||||
|
- # Don't repeat work.
|
||||||
|
- eval 'case "$h" in ('"$already"') continue;; esac'
|
||||||
|
-
|
||||||
|
- if grep -qE "$obsolete_type_re" "$h"; then
|
||||||
|
- echo "*** Obsolete types detected:"
|
||||||
|
- grep -HE "$obsolete_type_re" "$h"
|
||||||
|
- failed=1
|
||||||
|
- fi
|
||||||
|
- already="$already|$h"
|
||||||
|
- done
|
||||||
|
- else
|
||||||
|
- failed=1
|
||||||
|
+ then :
|
||||||
|
+ else failed=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
diff --git a/scripts/check-obsolete-constructs.py b/scripts/check-obsolete-constructs.py
|
||||||
|
new file mode 100755
|
||||||
|
index 0000000000000000..ce5c72251f4d7cc0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/scripts/check-obsolete-constructs.py
|
||||||
|
@@ -0,0 +1,466 @@
|
||||||
|
+#! /usr/bin/python3
|
||||||
|
+# Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+# This file is part of the GNU C Library.
|
||||||
|
+#
|
||||||
|
+# The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+# modify it under the terms of the GNU Lesser General Public
|
||||||
|
+# License as published by the Free Software Foundation; either
|
||||||
|
+# version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+#
|
||||||
|
+# The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+# Lesser General Public License for more details.
|
||||||
|
+#
|
||||||
|
+# You should have received a copy of the GNU Lesser General Public
|
||||||
|
+# License along with the GNU C Library; if not, see
|
||||||
|
+# <http://www.gnu.org/licenses/>.
|
||||||
|
+
|
||||||
|
+"""Verifies that installed headers do not use any obsolete constructs:
|
||||||
|
+ * legacy BSD typedefs superseded by <stdint.h>:
|
||||||
|
+ ushort uint ulong u_char u_short u_int u_long u_intNN_t quad_t u_quad_t
|
||||||
|
+ (sys/types.h is allowed to _define_ these types, but not to use them
|
||||||
|
+ to define anything else).
|
||||||
|
+"""
|
||||||
|
+
|
||||||
|
+import argparse
|
||||||
|
+import collections
|
||||||
|
+import re
|
||||||
|
+import sys
|
||||||
|
+
|
||||||
|
+# Simplified lexical analyzer for C preprocessing tokens.
|
||||||
|
+# Does not implement trigraphs.
|
||||||
|
+# Does not implement backslash-newline in the middle of any lexical
|
||||||
|
+# item other than a string literal.
|
||||||
|
+# Does not implement universal-character-names in identifiers.
|
||||||
|
+# Treats prefixed strings (e.g. L"...") as two tokens (L and "...")
|
||||||
|
+# Accepts non-ASCII characters only within comments and strings.
|
||||||
|
+
|
||||||
|
+# Caution: The order of the outermost alternation matters.
|
||||||
|
+# STRING must be before BAD_STRING, CHARCONST before BAD_CHARCONST,
|
||||||
|
+# BLOCK_COMMENT before BAD_BLOCK_COM before PUNCTUATOR, and OTHER must
|
||||||
|
+# be last.
|
||||||
|
+# Caution: There should be no capturing groups other than the named
|
||||||
|
+# captures in the outermost alternation.
|
||||||
|
+
|
||||||
|
+# For reference, these are all of the C punctuators as of C11:
|
||||||
|
+# [ ] ( ) { } , ; ? ~
|
||||||
|
+# ! != * *= / /= ^ ^= = ==
|
||||||
|
+# # ##
|
||||||
|
+# % %= %> %: %:%:
|
||||||
|
+# & &= &&
|
||||||
|
+# | |= ||
|
||||||
|
+# + += ++
|
||||||
|
+# - -= -- ->
|
||||||
|
+# . ...
|
||||||
|
+# : :>
|
||||||
|
+# < <% <: << <<= <=
|
||||||
|
+# > >= >> >>=
|
||||||
|
+
|
||||||
|
+# The BAD_* tokens are not part of the official definition of pp-tokens;
|
||||||
|
+# they match unclosed strings, character constants, and block comments,
|
||||||
|
+# so that the regex engine doesn't have to backtrack all the way to the
|
||||||
|
+# beginning of a broken construct and then emit dozens of junk tokens.
|
||||||
|
+
|
||||||
|
+PP_TOKEN_RE_ = re.compile(r"""
|
||||||
|
+ (?P<STRING> \"(?:[^\"\\\r\n]|\\(?:[\r\n -~]|\r\n))*\")
|
||||||
|
+ |(?P<BAD_STRING> \"(?:[^\"\\\r\n]|\\[ -~])*)
|
||||||
|
+ |(?P<CHARCONST> \'(?:[^\'\\\r\n]|\\(?:[\r\n -~]|\r\n))*\')
|
||||||
|
+ |(?P<BAD_CHARCONST> \'(?:[^\'\\\r\n]|\\[ -~])*)
|
||||||
|
+ |(?P<BLOCK_COMMENT> /\*(?:\*(?!/)|[^*])*\*/)
|
||||||
|
+ |(?P<BAD_BLOCK_COM> /\*(?:\*(?!/)|[^*])*\*?)
|
||||||
|
+ |(?P<LINE_COMMENT> //[^\r\n]*)
|
||||||
|
+ |(?P<IDENT> [_a-zA-Z][_a-zA-Z0-9]*)
|
||||||
|
+ |(?P<PP_NUMBER> \.?[0-9](?:[0-9a-df-oq-zA-DF-OQ-Z_.]|[eEpP][+-]?)*)
|
||||||
|
+ |(?P<PUNCTUATOR>
|
||||||
|
+ [,;?~(){}\[\]]
|
||||||
|
+ | [!*/^=]=?
|
||||||
|
+ | \#\#?
|
||||||
|
+ | %(?:[=>]|:(?:%:)?)?
|
||||||
|
+ | &[=&]?
|
||||||
|
+ |\|[=|]?
|
||||||
|
+ |\+[=+]?
|
||||||
|
+ | -[=->]?
|
||||||
|
+ |\.(?:\.\.)?
|
||||||
|
+ | :>?
|
||||||
|
+ | <(?:[%:]|<(?:=|<=?)?)?
|
||||||
|
+ | >(?:=|>=?)?)
|
||||||
|
+ |(?P<ESCNL> \\(?:\r|\n|\r\n))
|
||||||
|
+ |(?P<WHITESPACE> [ \t\n\r\v\f]+)
|
||||||
|
+ |(?P<OTHER> .)
|
||||||
|
+""", re.DOTALL | re.VERBOSE)
|
||||||
|
+
|
||||||
|
+HEADER_NAME_RE_ = re.compile(r"""
|
||||||
|
+ < [^>\r\n]+ >
|
||||||
|
+ | " [^"\r\n]+ "
|
||||||
|
+""", re.DOTALL | re.VERBOSE)
|
||||||
|
+
|
||||||
|
+ENDLINE_RE_ = re.compile(r"""\r|\n|\r\n""")
|
||||||
|
+
|
||||||
|
+# based on the sample code in the Python re documentation
|
||||||
|
+Token_ = collections.namedtuple("Token", (
|
||||||
|
+ "kind", "text", "line", "column", "context"))
|
||||||
|
+Token_.__doc__ = """
|
||||||
|
+ One C preprocessing token, comment, or chunk of whitespace.
|
||||||
|
+ 'kind' identifies the token type, which will be one of:
|
||||||
|
+ STRING, CHARCONST, BLOCK_COMMENT, LINE_COMMENT, IDENT,
|
||||||
|
+ PP_NUMBER, PUNCTUATOR, ESCNL, WHITESPACE, HEADER_NAME,
|
||||||
|
+ or OTHER. The BAD_* alternatives in PP_TOKEN_RE_ are
|
||||||
|
+ handled within tokenize_c, below.
|
||||||
|
+
|
||||||
|
+ 'text' is the sequence of source characters making up the token;
|
||||||
|
+ no decoding whatsoever is performed.
|
||||||
|
+
|
||||||
|
+ 'line' and 'column' give the position of the first character of the
|
||||||
|
+ token within the source file. They are both 1-based.
|
||||||
|
+
|
||||||
|
+ 'context' indicates whether or not this token occurred within a
|
||||||
|
+ preprocessing directive; it will be None for running text,
|
||||||
|
+ '<null>' for the leading '#' of a directive line (because '#'
|
||||||
|
+ all by itself on a line is a "null directive"), or the name of
|
||||||
|
+ the directive for tokens within a directive line, starting with
|
||||||
|
+ the IDENT for the name itself.
|
||||||
|
+"""
|
||||||
|
+
|
||||||
|
+def tokenize_c(file_contents, reporter):
|
||||||
|
+ """Yield a series of Token objects, one for each preprocessing
|
||||||
|
+ token, comment, or chunk of whitespace within FILE_CONTENTS.
|
||||||
|
+ The REPORTER object is expected to have one method,
|
||||||
|
+ reporter.error(token, message), which will be called to
|
||||||
|
+ indicate a lexical error at the position of TOKEN.
|
||||||
|
+ If MESSAGE contains the four-character sequence '{!r}', that
|
||||||
|
+ is expected to be replaced by repr(token.text).
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ Token = Token_
|
||||||
|
+ PP_TOKEN_RE = PP_TOKEN_RE_
|
||||||
|
+ ENDLINE_RE = ENDLINE_RE_
|
||||||
|
+ HEADER_NAME_RE = HEADER_NAME_RE_
|
||||||
|
+
|
||||||
|
+ line_num = 1
|
||||||
|
+ line_start = 0
|
||||||
|
+ pos = 0
|
||||||
|
+ limit = len(file_contents)
|
||||||
|
+ directive = None
|
||||||
|
+ at_bol = True
|
||||||
|
+ while pos < limit:
|
||||||
|
+ if directive == "include":
|
||||||
|
+ mo = HEADER_NAME_RE.match(file_contents, pos)
|
||||||
|
+ if mo:
|
||||||
|
+ kind = "HEADER_NAME"
|
||||||
|
+ directive = "after_include"
|
||||||
|
+ else:
|
||||||
|
+ mo = PP_TOKEN_RE.match(file_contents, pos)
|
||||||
|
+ kind = mo.lastgroup
|
||||||
|
+ if kind != "WHITESPACE":
|
||||||
|
+ directive = "after_include"
|
||||||
|
+ else:
|
||||||
|
+ mo = PP_TOKEN_RE.match(file_contents, pos)
|
||||||
|
+ kind = mo.lastgroup
|
||||||
|
+
|
||||||
|
+ text = mo.group()
|
||||||
|
+ line = line_num
|
||||||
|
+ column = mo.start() - line_start
|
||||||
|
+ adj_line_start = 0
|
||||||
|
+ # only these kinds can contain a newline
|
||||||
|
+ if kind in ("WHITESPACE", "BLOCK_COMMENT", "LINE_COMMENT",
|
||||||
|
+ "STRING", "CHARCONST", "BAD_BLOCK_COM", "ESCNL"):
|
||||||
|
+ for tmo in ENDLINE_RE.finditer(text):
|
||||||
|
+ line_num += 1
|
||||||
|
+ adj_line_start = tmo.end()
|
||||||
|
+ if adj_line_start:
|
||||||
|
+ line_start = mo.start() + adj_line_start
|
||||||
|
+
|
||||||
|
+ # Track whether or not we are scanning a preprocessing directive.
|
||||||
|
+ if kind == "LINE_COMMENT" or (kind == "WHITESPACE" and adj_line_start):
|
||||||
|
+ at_bol = True
|
||||||
|
+ directive = None
|
||||||
|
+ else:
|
||||||
|
+ if kind == "PUNCTUATOR" and text == "#" and at_bol:
|
||||||
|
+ directive = "<null>"
|
||||||
|
+ elif kind == "IDENT" and directive == "<null>":
|
||||||
|
+ directive = text
|
||||||
|
+ at_bol = False
|
||||||
|
+
|
||||||
|
+ # Report ill-formed tokens and rewrite them as their well-formed
|
||||||
|
+ # equivalents, so downstream processing doesn't have to know about them.
|
||||||
|
+ # (Rewriting instead of discarding provides better error recovery.)
|
||||||
|
+ if kind == "BAD_BLOCK_COM":
|
||||||
|
+ reporter.error(Token("BAD_BLOCK_COM", "", line, column+1, ""),
|
||||||
|
+ "unclosed block comment")
|
||||||
|
+ text += "*/"
|
||||||
|
+ kind = "BLOCK_COMMENT"
|
||||||
|
+ elif kind == "BAD_STRING":
|
||||||
|
+ reporter.error(Token("BAD_STRING", "", line, column+1, ""),
|
||||||
|
+ "unclosed string")
|
||||||
|
+ text += "\""
|
||||||
|
+ kind = "STRING"
|
||||||
|
+ elif kind == "BAD_CHARCONST":
|
||||||
|
+ reporter.error(Token("BAD_CHARCONST", "", line, column+1, ""),
|
||||||
|
+ "unclosed char constant")
|
||||||
|
+ text += "'"
|
||||||
|
+ kind = "CHARCONST"
|
||||||
|
+
|
||||||
|
+ tok = Token(kind, text, line, column+1,
|
||||||
|
+ "include" if directive == "after_include" else directive)
|
||||||
|
+ # Do not complain about OTHER tokens inside macro definitions.
|
||||||
|
+ # $ and @ appear in macros defined by headers intended to be
|
||||||
|
+ # included from assembly language, e.g. sysdeps/mips/sys/asm.h.
|
||||||
|
+ if kind == "OTHER" and directive != "define":
|
||||||
|
+ self.error(tok, "stray {!r} in program")
|
||||||
|
+
|
||||||
|
+ yield tok
|
||||||
|
+ pos = mo.end()
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Base and generic classes for individual checks.
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+class ConstructChecker:
|
||||||
|
+ """Scan a stream of C preprocessing tokens and possibly report
|
||||||
|
+ problems with them. The REPORTER object passed to __init__ has
|
||||||
|
+ one method, reporter.error(token, message), which should be
|
||||||
|
+ called to indicate a problem detected at the position of TOKEN.
|
||||||
|
+ If MESSAGE contains the four-character sequence '{!r}' then that
|
||||||
|
+ will be replaced with a textual representation of TOKEN.
|
||||||
|
+ """
|
||||||
|
+ def __init__(self, reporter):
|
||||||
|
+ self.reporter = reporter
|
||||||
|
+
|
||||||
|
+ def examine(self, tok):
|
||||||
|
+ """Called once for each token in a header file.
|
||||||
|
+ Call self.reporter.error if a problem is detected.
|
||||||
|
+ """
|
||||||
|
+ raise NotImplementedError
|
||||||
|
+
|
||||||
|
+ def eof(self):
|
||||||
|
+ """Called once at the end of the stream. Subclasses need only
|
||||||
|
+ override this if it might have something to do."""
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+class NoCheck(ConstructChecker):
|
||||||
|
+ """Generic checker class which doesn't do anything. Substitute this
|
||||||
|
+ class for a real checker when a particular check should be skipped
|
||||||
|
+ for some file."""
|
||||||
|
+
|
||||||
|
+ def examine(self, tok):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Check for obsolete type names.
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+# The obsolete type names we're looking for:
|
||||||
|
+OBSOLETE_TYPE_RE_ = re.compile(r"""\A
|
||||||
|
+ (__)?
|
||||||
|
+ ( quad_t
|
||||||
|
+ | u(?: short | int | long
|
||||||
|
+ | _(?: char | short | int(?:[0-9]+_t)? | long | quad_t )))
|
||||||
|
+\Z""", re.VERBOSE)
|
||||||
|
+
|
||||||
|
+class ObsoleteNotAllowed(ConstructChecker):
|
||||||
|
+ """Don't allow any use of the obsolete typedefs."""
|
||||||
|
+ def examine(self, tok):
|
||||||
|
+ if OBSOLETE_TYPE_RE_.match(tok.text):
|
||||||
|
+ self.reporter.error(tok, "use of {!r}")
|
||||||
|
+
|
||||||
|
+class ObsoletePrivateDefinitionsAllowed(ConstructChecker):
|
||||||
|
+ """Allow definitions of the private versions of the
|
||||||
|
+ obsolete typedefs; that is, 'typedef [anything] __obsolete;'
|
||||||
|
+ """
|
||||||
|
+ def __init__(self, reporter):
|
||||||
|
+ super().__init__(reporter)
|
||||||
|
+ self.in_typedef = False
|
||||||
|
+ self.prev_token = None
|
||||||
|
+
|
||||||
|
+ def examine(self, tok):
|
||||||
|
+ # bits/types.h hides 'typedef' in a macro sometimes.
|
||||||
|
+ if (tok.kind == "IDENT"
|
||||||
|
+ and tok.text in ("typedef", "__STD_TYPE")
|
||||||
|
+ and tok.context is None):
|
||||||
|
+ self.in_typedef = True
|
||||||
|
+ elif tok.kind == "PUNCTUATOR" and tok.text == ";" and self.in_typedef:
|
||||||
|
+ self.in_typedef = False
|
||||||
|
+ if self.prev_token.kind == "IDENT":
|
||||||
|
+ m = OBSOLETE_TYPE_RE_.match(self.prev_token.text)
|
||||||
|
+ if m and m.group(1) != "__":
|
||||||
|
+ self.reporter.error(self.prev_token, "use of {!r}")
|
||||||
|
+ self.prev_token = None
|
||||||
|
+ else:
|
||||||
|
+ self._check_prev()
|
||||||
|
+
|
||||||
|
+ self.prev_token = tok
|
||||||
|
+
|
||||||
|
+ def eof(self):
|
||||||
|
+ self._check_prev()
|
||||||
|
+
|
||||||
|
+ def _check_prev(self):
|
||||||
|
+ if (self.prev_token is not None
|
||||||
|
+ and self.prev_token.kind == "IDENT"
|
||||||
|
+ and OBSOLETE_TYPE_RE_.match(self.prev_token.text)):
|
||||||
|
+ self.reporter.error(self.prev_token, "use of {!r}")
|
||||||
|
+
|
||||||
|
+class ObsoletePublicDefinitionsAllowed(ConstructChecker):
|
||||||
|
+ """Allow definitions of the public versions of the obsolete
|
||||||
|
+ typedefs. Only specific forms of definition are allowed:
|
||||||
|
+
|
||||||
|
+ typedef __obsolete obsolete; // identifiers must agree
|
||||||
|
+ typedef __uintN_t u_intN_t; // N must agree
|
||||||
|
+ typedef unsigned long int ulong;
|
||||||
|
+ typedef unsigned short int ushort;
|
||||||
|
+ typedef unsigned int uint;
|
||||||
|
+ """
|
||||||
|
+ def __init__(self, reporter):
|
||||||
|
+ super().__init__(reporter)
|
||||||
|
+ self.typedef_tokens = []
|
||||||
|
+
|
||||||
|
+ def examine(self, tok):
|
||||||
|
+ if tok.kind in ("WHITESPACE", "BLOCK_COMMENT",
|
||||||
|
+ "LINE_COMMENT", "NL", "ESCNL"):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ elif (tok.kind == "IDENT" and tok.text == "typedef"
|
||||||
|
+ and tok.context is None):
|
||||||
|
+ if self.typedef_tokens:
|
||||||
|
+ self.reporter.error(tok, "typedef inside typedef")
|
||||||
|
+ self._reset()
|
||||||
|
+ self.typedef_tokens.append(tok)
|
||||||
|
+
|
||||||
|
+ elif tok.kind == "PUNCTUATOR" and tok.text == ";":
|
||||||
|
+ self._finish()
|
||||||
|
+
|
||||||
|
+ elif self.typedef_tokens:
|
||||||
|
+ self.typedef_tokens.append(tok)
|
||||||
|
+
|
||||||
|
+ def eof(self):
|
||||||
|
+ self._reset()
|
||||||
|
+
|
||||||
|
+ def _reset(self):
|
||||||
|
+ while self.typedef_tokens:
|
||||||
|
+ tok = self.typedef_tokens.pop(0)
|
||||||
|
+ if tok.kind == "IDENT" and OBSOLETE_TYPE_RE_.match(tok.text):
|
||||||
|
+ self.reporter.error(tok, "use of {!r}")
|
||||||
|
+
|
||||||
|
+ def _finish(self):
|
||||||
|
+ if not self.typedef_tokens: return
|
||||||
|
+ if self.typedef_tokens[-1].kind == "IDENT":
|
||||||
|
+ m = OBSOLETE_TYPE_RE_.match(self.typedef_tokens[-1].text)
|
||||||
|
+ if m:
|
||||||
|
+ if self._permissible_public_definition(m):
|
||||||
|
+ self.typedef_tokens.clear()
|
||||||
|
+ self._reset()
|
||||||
|
+
|
||||||
|
+ def _permissible_public_definition(self, m):
|
||||||
|
+ if m.group(1) == "__": return False
|
||||||
|
+ name = m.group(2)
|
||||||
|
+ toks = self.typedef_tokens
|
||||||
|
+ ntok = len(toks)
|
||||||
|
+ if ntok == 3 and toks[1].kind == "IDENT":
|
||||||
|
+ defn = toks[1].text
|
||||||
|
+ n = OBSOLETE_TYPE_RE_.match(defn)
|
||||||
|
+ if n and n.group(1) == "__" and n.group(2) == name:
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ if (name[:5] == "u_int" and name[-2:] == "_t"
|
||||||
|
+ and defn[:6] == "__uint" and defn[-2:] == "_t"
|
||||||
|
+ and name[5:-2] == defn[6:-2]):
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+ if (name == "ulong" and ntok == 5
|
||||||
|
+ and toks[1].kind == "IDENT" and toks[1].text == "unsigned"
|
||||||
|
+ and toks[2].kind == "IDENT" and toks[2].text == "long"
|
||||||
|
+ and toks[3].kind == "IDENT" and toks[3].text == "int"):
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ if (name == "ushort" and ntok == 5
|
||||||
|
+ and toks[1].kind == "IDENT" and toks[1].text == "unsigned"
|
||||||
|
+ and toks[2].kind == "IDENT" and toks[2].text == "short"
|
||||||
|
+ and toks[3].kind == "IDENT" and toks[3].text == "int"):
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ if (name == "uint" and ntok == 4
|
||||||
|
+ and toks[1].kind == "IDENT" and toks[1].text == "unsigned"
|
||||||
|
+ and toks[2].kind == "IDENT" and toks[2].text == "int"):
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+def ObsoleteTypedefChecker(reporter, fname):
|
||||||
|
+ """Factory: produce an instance of the appropriate
|
||||||
|
+ obsolete-typedef checker for FNAME."""
|
||||||
|
+
|
||||||
|
+ # The obsolete rpc/ and rpcsvc/ headers are allowed to use the
|
||||||
|
+ # obsolete types, because it would be more trouble than it's
|
||||||
|
+ # worth to remove them from headers that we intend to stop
|
||||||
|
+ # installing eventually anyway.
|
||||||
|
+ if (fname.startswith("rpc/")
|
||||||
|
+ or fname.startswith("rpcsvc/")
|
||||||
|
+ or "/rpc/" in fname
|
||||||
|
+ or "/rpcsvc/" in fname):
|
||||||
|
+ return NoCheck(reporter)
|
||||||
|
+
|
||||||
|
+ # bits/types.h is allowed to define the __-versions of the
|
||||||
|
+ # obsolete types.
|
||||||
|
+ if (fname == "bits/types.h"
|
||||||
|
+ or fname.endswith("/bits/types.h")):
|
||||||
|
+ return ObsoletePrivateDefinitionsAllowed(reporter)
|
||||||
|
+
|
||||||
|
+ # sys/types.h is allowed to use the __-versions of the
|
||||||
|
+ # obsolete types, but only to define the unprefixed versions.
|
||||||
|
+ if (fname == "sys/types.h"
|
||||||
|
+ or fname.endswith("/sys/types.h")):
|
||||||
|
+ return ObsoletePublicDefinitionsAllowed(reporter)
|
||||||
|
+
|
||||||
|
+ return ObsoleteNotAllowed(reporter)
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Master control
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+class HeaderChecker:
|
||||||
|
+ """Perform all of the checks on each header. This is also the
|
||||||
|
+ "reporter" object expected by tokenize_c and ConstructChecker.
|
||||||
|
+ """
|
||||||
|
+ def __init__(self):
|
||||||
|
+ self.fname = None
|
||||||
|
+ self.status = 0
|
||||||
|
+
|
||||||
|
+ def error(self, tok, message):
|
||||||
|
+ self.status = 1
|
||||||
|
+ if '{!r}' in message:
|
||||||
|
+ message = message.format(tok.text)
|
||||||
|
+ sys.stderr.write("{}:{}:{}: error: {}\n".format(
|
||||||
|
+ self.fname, tok.line, tok.column, message))
|
||||||
|
+
|
||||||
|
+ def check(self, fname):
|
||||||
|
+ self.fname = fname
|
||||||
|
+ try:
|
||||||
|
+ with open(fname, "rt") as fp:
|
||||||
|
+ contents = fp.read()
|
||||||
|
+ except OSError as e:
|
||||||
|
+ sys.stderr.write("{}: {}\n".format(fname, e.strerror))
|
||||||
|
+ self.status = 1
|
||||||
|
+ return
|
||||||
|
+
|
||||||
|
+ typedef_checker = ObsoleteTypedefChecker(self, self.fname)
|
||||||
|
+
|
||||||
|
+ for tok in tokenize_c(contents, self):
|
||||||
|
+ typedef_checker.examine(tok)
|
||||||
|
+
|
||||||
|
+def main():
|
||||||
|
+ ap = argparse.ArgumentParser(description=__doc__)
|
||||||
|
+ ap.add_argument("headers", metavar="header", nargs="+",
|
||||||
|
+ help="one or more headers to scan for obsolete constructs")
|
||||||
|
+ args = ap.parse_args()
|
||||||
|
+
|
||||||
|
+ checker = HeaderChecker()
|
||||||
|
+ for fname in args.headers:
|
||||||
|
+ # Headers whose installed name begins with "finclude/" contain
|
||||||
|
+ # Fortran, not C, and this program should completely ignore them.
|
||||||
|
+ if not (fname.startswith("finclude/") or "/finclude/" in fname):
|
||||||
|
+ checker.check(fname)
|
||||||
|
+ sys.exit(checker.status)
|
||||||
|
+
|
||||||
|
+main()
|
24
SOURCES/glibc-rh1774021.patch
Normal file
24
SOURCES/glibc-rh1774021.patch
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
commit d5dfad4326fc683c813df1e37bbf5cf920591c8e
|
||||||
|
Author: Marcin Kościelnicki <mwk@0x04.net>
|
||||||
|
Date: Thu Nov 21 00:20:15 2019 +0100
|
||||||
|
|
||||||
|
rtld: Check __libc_enable_secure before honoring LD_PREFER_MAP_32BIT_EXEC (CVE-2019-19126) [BZ #25204]
|
||||||
|
|
||||||
|
The problem was introduced in glibc 2.23, in commit
|
||||||
|
b9eb92ab05204df772eb4929eccd018637c9f3e9
|
||||||
|
("Add Prefer_MAP_32BIT_EXEC to map executable pages with MAP_32BIT").
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h
|
||||||
|
index 194369174df08946..ac694c032e7baf87 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h
|
||||||
|
@@ -31,7 +31,8 @@
|
||||||
|
environment variable, LD_PREFER_MAP_32BIT_EXEC. */
|
||||||
|
#define EXTRA_LD_ENVVARS \
|
||||||
|
case 21: \
|
||||||
|
- if (memcmp (envline, "PREFER_MAP_32BIT_EXEC", 21) == 0) \
|
||||||
|
+ if (!__libc_enable_secure \
|
||||||
|
+ && memcmp (envline, "PREFER_MAP_32BIT_EXEC", 21) == 0) \
|
||||||
|
GLRO(dl_x86_cpu_features).feature[index_arch_Prefer_MAP_32BIT_EXEC] \
|
||||||
|
|= bit_arch_Prefer_MAP_32BIT_EXEC; \
|
||||||
|
break;
|
70
SOURCES/glibc-rh1775294.patch
Normal file
70
SOURCES/glibc-rh1775294.patch
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
commit bfa864e1645e140da2e1aae3cf0d0ba0674f6eb5
|
||||||
|
Author: Emilio Cobos Álvarez <emilio@crisal.io>
|
||||||
|
Date: Tue Nov 12 19:18:32 2019 +0100
|
||||||
|
|
||||||
|
Don't use a custom wrapper macro around __has_include (bug 25189).
|
||||||
|
|
||||||
|
This causes issues when using clang with -frewrite-includes to e.g.,
|
||||||
|
submit the translation unit to a distributed compiler.
|
||||||
|
|
||||||
|
In my case, I was building Firefox using sccache.
|
||||||
|
|
||||||
|
See [1] for a reduced test-case since I initially thought this was a
|
||||||
|
clang bug, and [2] for more context.
|
||||||
|
|
||||||
|
Apparently doing this is invalid C++ per [cpp.cond], which mentions [3]:
|
||||||
|
|
||||||
|
> The #ifdef and #ifndef directives, and the defined conditional
|
||||||
|
> inclusion operator, shall treat __has_include and __has_cpp_attribute
|
||||||
|
> as if they were the names of defined macros. The identifiers
|
||||||
|
> __has_include and __has_cpp_attribute shall not appear in any context
|
||||||
|
> not mentioned in this subclause.
|
||||||
|
|
||||||
|
[1]: https://bugs.llvm.org/show_bug.cgi?id=43982
|
||||||
|
[2]: https://bugs.llvm.org/show_bug.cgi?id=37990
|
||||||
|
[3]: http://eel.is/c++draft/cpp.cond#7.sentence-2
|
||||||
|
|
||||||
|
Change-Id: Id4b8ee19176a9e4624b533087ba870c418f27e60
|
||||||
|
|
||||||
|
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
|
||||||
|
index 9e840e602f815d86..3f6fe3cc8563b493 100644
|
||||||
|
--- a/misc/sys/cdefs.h
|
||||||
|
+++ b/misc/sys/cdefs.h
|
||||||
|
@@ -412,14 +412,6 @@
|
||||||
|
# define __glibc_has_attribute(attr) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-#ifdef __has_include
|
||||||
|
-/* Do not use a function-like macro, so that __has_include can inhibit
|
||||||
|
- macro expansion. */
|
||||||
|
-# define __glibc_has_include __has_include
|
||||||
|
-#else
|
||||||
|
-# define __glibc_has_include(header) 0
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
#if (!defined _Noreturn \
|
||||||
|
&& (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
|
||||||
|
&& !__GNUC_PREREQ (4,7))
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/bits/statx.h b/sysdeps/unix/sysv/linux/bits/statx.h
|
||||||
|
index 206878723fd37881..aaccfdc2dc03a1dc 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/bits/statx.h
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/bits/statx.h
|
||||||
|
@@ -26,11 +26,13 @@
|
||||||
|
|
||||||
|
/* Use "" to work around incorrect macro expansion of the
|
||||||
|
__has_include argument (GCC PR 80005). */
|
||||||
|
-#if __glibc_has_include ("linux/stat.h")
|
||||||
|
-# include "linux/stat.h"
|
||||||
|
-# ifdef STATX_TYPE
|
||||||
|
-# define __statx_timestamp_defined 1
|
||||||
|
-# define __statx_defined 1
|
||||||
|
+#ifdef __has_include
|
||||||
|
+# if __has_include ("linux/stat.h")
|
||||||
|
+# include "linux/stat.h"
|
||||||
|
+# ifdef STATX_TYPE
|
||||||
|
+# define __statx_timestamp_defined 1
|
||||||
|
+# define __statx_defined 1
|
||||||
|
+# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
#
|
|
||||||
# /etc/nsswitch.conf
|
|
||||||
#
|
|
||||||
# An example Name Service Switch config file. This file should be
|
|
||||||
# sorted with the most-used services at the beginning.
|
|
||||||
#
|
|
||||||
# The entry '[NOTFOUND=return]' means that the search for an
|
|
||||||
# entry should stop if the search in the previous entry turned
|
|
||||||
# up nothing. Note that if the search failed due to some other reason
|
|
||||||
# (like no NIS server responding) then the search continues with the
|
|
||||||
# next entry.
|
|
||||||
#
|
|
||||||
# Valid entries include:
|
|
||||||
#
|
|
||||||
# nisplus Use NIS+ (NIS version 3)
|
|
||||||
# nis Use NIS (NIS version 2), also called YP
|
|
||||||
# dns Use DNS (Domain Name Service)
|
|
||||||
# files Use the local files in /etc
|
|
||||||
# db Use the pre-processed /var/db files
|
|
||||||
# compat Use /etc files plus *_compat pseudo-databases
|
|
||||||
# hesiod Use Hesiod (DNS) for user lookups
|
|
||||||
# sss Use sssd (System Security Services Daemon)
|
|
||||||
# [NOTFOUND=return] Stop searching if not found so far
|
|
||||||
#
|
|
||||||
# 'sssd' performs its own 'files'-based caching, so it should
|
|
||||||
# generally come before 'files'.
|
|
||||||
|
|
||||||
# To use 'db', install the nss_db package, and put the 'db' in front
|
|
||||||
# of 'files' for entries you want to be looked up first in the
|
|
||||||
# databases, like this:
|
|
||||||
#
|
|
||||||
# passwd: db files
|
|
||||||
# shadow: db files
|
|
||||||
# group: db files
|
|
||||||
|
|
||||||
passwd: sss files
|
|
||||||
shadow: files sss
|
|
||||||
group: sss files
|
|
||||||
|
|
||||||
hosts: files dns myhostname
|
|
||||||
|
|
||||||
bootparams: files
|
|
||||||
|
|
||||||
ethers: files
|
|
||||||
netmasks: files
|
|
||||||
networks: files
|
|
||||||
protocols: files
|
|
||||||
rpc: files
|
|
||||||
services: files sss
|
|
||||||
|
|
||||||
netgroup: sss
|
|
||||||
|
|
||||||
publickey: files
|
|
||||||
|
|
||||||
automount: files sss
|
|
||||||
aliases: files
|
|
179
SPECS/glibc.spec
179
SPECS/glibc.spec
@ -1,6 +1,6 @@
|
|||||||
%define glibcsrcdir glibc-2.28
|
%define glibcsrcdir glibc-2.28
|
||||||
%define glibcversion 2.28
|
%define glibcversion 2.28
|
||||||
%define glibcrelease 72%{?dist}.1
|
%define glibcrelease 101%{?dist}
|
||||||
# Pre-release tarballs are pulled in from git using a command that is
|
# Pre-release tarballs are pulled in from git using a command that is
|
||||||
# effectively:
|
# effectively:
|
||||||
#
|
#
|
||||||
@ -121,7 +121,6 @@ URL: http://www.gnu.org/software/glibc/
|
|||||||
Source0: %{?glibc_release_url}%{glibcsrcdir}.tar.xz
|
Source0: %{?glibc_release_url}%{glibcsrcdir}.tar.xz
|
||||||
Source1: build-locale-archive.c
|
Source1: build-locale-archive.c
|
||||||
Source4: nscd.conf
|
Source4: nscd.conf
|
||||||
Source7: nsswitch.conf
|
|
||||||
Source8: power6emul.c
|
Source8: power6emul.c
|
||||||
Source9: bench.mk
|
Source9: bench.mk
|
||||||
Source10: glibc-bench-compare
|
Source10: glibc-bench-compare
|
||||||
@ -315,7 +314,88 @@ Patch180: glibc-rh1717438.patch
|
|||||||
Patch181: glibc-rh1727152.patch
|
Patch181: glibc-rh1727152.patch
|
||||||
Patch182: glibc-rh1724975.patch
|
Patch182: glibc-rh1724975.patch
|
||||||
Patch183: glibc-rh1722215.patch
|
Patch183: glibc-rh1722215.patch
|
||||||
Patch184: glibc-rh1777797.patch
|
Patch184: glibc-rh1764234-1.patch
|
||||||
|
Patch185: glibc-rh1764234-2.patch
|
||||||
|
Patch186: glibc-rh1764234-3.patch
|
||||||
|
Patch187: glibc-rh1764234-4.patch
|
||||||
|
Patch188: glibc-rh1764234-5.patch
|
||||||
|
Patch189: glibc-rh1764234-6.patch
|
||||||
|
Patch190: glibc-rh1764234-7.patch
|
||||||
|
Patch191: glibc-rh1764234-8.patch
|
||||||
|
Patch192: glibc-rh1747505-1.patch
|
||||||
|
Patch193: glibc-rh1747505-2.patch
|
||||||
|
Patch194: glibc-rh1747505-3.patch
|
||||||
|
Patch195: glibc-rh1747505-4.patch
|
||||||
|
Patch196: glibc-rh1747453.patch
|
||||||
|
Patch197: glibc-rh1764241.patch
|
||||||
|
Patch198: glibc-rh1746933-1.patch
|
||||||
|
Patch199: glibc-rh1746933-2.patch
|
||||||
|
Patch200: glibc-rh1746933-3.patch
|
||||||
|
Patch201: glibc-rh1735747-1.patch
|
||||||
|
Patch202: glibc-rh1735747-2.patch
|
||||||
|
Patch203: glibc-rh1764226-1.patch
|
||||||
|
Patch204: glibc-rh1764226-2.patch
|
||||||
|
Patch205: glibc-rh1764226-3.patch
|
||||||
|
Patch206: glibc-rh1764218-1.patch
|
||||||
|
Patch207: glibc-rh1764218-2.patch
|
||||||
|
Patch208: glibc-rh1764218-3.patch
|
||||||
|
Patch209: glibc-rh1682954.patch
|
||||||
|
Patch210: glibc-rh1746928.patch
|
||||||
|
Patch211: glibc-rh1747502.patch
|
||||||
|
Patch212: glibc-rh1747502-1.patch
|
||||||
|
Patch213: glibc-rh1747502-2.patch
|
||||||
|
Patch214: glibc-rh1747502-3.patch
|
||||||
|
Patch215: glibc-rh1747502-4.patch
|
||||||
|
Patch216: glibc-rh1747502-5.patch
|
||||||
|
Patch217: glibc-rh1747502-6.patch
|
||||||
|
Patch218: glibc-rh1747502-7.patch
|
||||||
|
Patch219: glibc-rh1747502-8.patch
|
||||||
|
Patch220: glibc-rh1747502-9.patch
|
||||||
|
Patch221: glibc-rh1726638-1.patch
|
||||||
|
Patch222: glibc-rh1726638-2.patch
|
||||||
|
Patch223: glibc-rh1726638-3.patch
|
||||||
|
Patch224: glibc-rh1764238-1.patch
|
||||||
|
Patch225: glibc-rh1764238-2.patch
|
||||||
|
Patch226: glibc-rh1764242.patch
|
||||||
|
Patch227: glibc-rh1769304.patch
|
||||||
|
Patch228: glibc-rh1749439-1.patch
|
||||||
|
Patch229: glibc-rh1749439-2.patch
|
||||||
|
Patch230: glibc-rh1749439-3.patch
|
||||||
|
Patch231: glibc-rh1749439-4.patch
|
||||||
|
Patch232: glibc-rh1749439-5.patch
|
||||||
|
Patch233: glibc-rh1749439-6.patch
|
||||||
|
Patch234: glibc-rh1749439-7.patch
|
||||||
|
Patch235: glibc-rh1749439-8.patch
|
||||||
|
Patch236: glibc-rh1749439-9.patch
|
||||||
|
Patch237: glibc-rh1749439-10.patch
|
||||||
|
Patch238: glibc-rh1749439-11.patch
|
||||||
|
Patch239: glibc-rh1749439-12.patch
|
||||||
|
Patch240: glibc-rh1749439-13.patch
|
||||||
|
Patch241: glibc-rh1764231-1.patch
|
||||||
|
Patch242: glibc-rh1764231-2.patch
|
||||||
|
Patch243: glibc-rh1764235.patch
|
||||||
|
Patch244: glibc-rh1361965.patch
|
||||||
|
Patch245: glibc-rh1764223.patch
|
||||||
|
Patch246: glibc-rh1764214.patch
|
||||||
|
Patch247: glibc-rh1774021.patch
|
||||||
|
Patch248: glibc-rh1775294.patch
|
||||||
|
Patch249: glibc-rh1777241.patch
|
||||||
|
Patch250: glibc-rh1410154-1.patch
|
||||||
|
Patch251: glibc-rh1410154-2.patch
|
||||||
|
Patch252: glibc-rh1410154-3.patch
|
||||||
|
Patch253: glibc-rh1410154-4.patch
|
||||||
|
Patch254: glibc-rh1410154-5.patch
|
||||||
|
Patch255: glibc-rh1410154-6.patch
|
||||||
|
Patch256: glibc-rh1410154-7.patch
|
||||||
|
Patch257: glibc-rh1410154-8.patch
|
||||||
|
Patch258: glibc-rh1410154-9.patch
|
||||||
|
Patch259: glibc-rh1410154-10.patch
|
||||||
|
Patch260: glibc-rh1410154-11.patch
|
||||||
|
Patch261: glibc-rh1410154-12.patch
|
||||||
|
Patch262: glibc-rh1410154-13.patch
|
||||||
|
Patch263: glibc-rh1410154-14.patch
|
||||||
|
Patch264: glibc-rh1410154-15.patch
|
||||||
|
Patch265: glibc-rh1410154-16.patch
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Continued list of core "glibc" package information:
|
# Continued list of core "glibc" package information:
|
||||||
@ -1238,7 +1318,7 @@ mv %{glibc_sysroot}%{_prefix}/lib/locale/*.filelist .
|
|||||||
# Install configuration files for services
|
# Install configuration files for services
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
install -p -m 644 %{SOURCE7} %{glibc_sysroot}/etc/nsswitch.conf
|
install -p -m 644 nss/nsswitch.conf %{glibc_sysroot}/etc/nsswitch.conf
|
||||||
|
|
||||||
%ifnarch %{auxarches}
|
%ifnarch %{auxarches}
|
||||||
# This is for ncsd - in glibc 2.2
|
# This is for ncsd - in glibc 2.2
|
||||||
@ -2202,8 +2282,95 @@ fi
|
|||||||
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Thu Nov 28 2019 Florian Weimer <fweimer@redhat.com> - 2.28-72.1
|
* Thu Jan 16 2020 Florian Weimer <fweimer@redhat.com> - 2.28-101
|
||||||
- s390x: Fix z15 strstr for patterns crossing pages (#1777797)
|
- ld.so: Reset GL (dl_initfirst) pointer on dlopen failure (#1410154)
|
||||||
|
|
||||||
|
* Fri Dec 13 2019 Florian Weimer <fweimer@redhat.com> - 2.28-100
|
||||||
|
- Roll back dynamic linker state on dlopen failure (#1410154)
|
||||||
|
|
||||||
|
* Wed Nov 27 2019 Florian Weimer <fweimer@redhat.com> - 2.28-99
|
||||||
|
- s390x: Fix z15 strstr for patterns crossing pages (#1777241)
|
||||||
|
|
||||||
|
* Wed Nov 27 2019 Florian Weimer <fweimer@redhat.com> - 2.28-98
|
||||||
|
- Rebuild with new rpm (#1654901)
|
||||||
|
|
||||||
|
* Fri Nov 22 2019 Florian Weimer <fweimer@redhat.com> - 2.28-97
|
||||||
|
- Avoid invalid __has_include in <sys/stat.h> (#1775294)
|
||||||
|
|
||||||
|
* Fri Nov 22 2019 Florian Weimer <fweimer@redhat.com> - 2.28-96
|
||||||
|
- x86-64: Ignore LD_PREFER_MAP_32BIT_EXEC in SUID binaries (#1774021)
|
||||||
|
|
||||||
|
* Thu Nov 14 2019 DJ Delorie <dj@redhat.com> - 2.28-95
|
||||||
|
- Fix alignment of TLS variables for tls variant TLS_TCB_AT_TP (#1764214)
|
||||||
|
|
||||||
|
* Thu Nov 14 2019 DJ Delorie <dj@redhat.com> - 2.28-94
|
||||||
|
- Refuse to dlopen PIE objects (#1764223)
|
||||||
|
|
||||||
|
* Thu Nov 14 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-93
|
||||||
|
- Fix C.UTF-8 locale source ellipsis expressions (#1361965)
|
||||||
|
|
||||||
|
* Thu Nov 14 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-92
|
||||||
|
- Fix hangs during malloc tracing (#1764235)
|
||||||
|
|
||||||
|
* Thu Nov 14 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-91
|
||||||
|
- Support moving versioned symbols between sonames (#1764231)
|
||||||
|
|
||||||
|
* Wed Nov 13 2019 Florian Weimer <fweimer@redhat.com> - 2.28-90
|
||||||
|
- Avoid creating stale utmp entries for repeated pututxline (#1749439)
|
||||||
|
|
||||||
|
* Wed Nov 6 2019 Florian Weimer <fweimer@redhat.com> - 2.28-89
|
||||||
|
- Backport more precise tokenizer for installed headers test (#1769304)
|
||||||
|
|
||||||
|
* Wed Nov 6 2019 Florian Weimer <fweimer@redhat.com> - 2.28-88
|
||||||
|
- math: Enable some math builtins for clang in LLVM Toolset (#1764242)
|
||||||
|
|
||||||
|
* Wed Nov 6 2019 Florian Weimer <fweimer@redhat.com> - 2.28-87
|
||||||
|
- Support Fortran vectorized math functions with GCC Toolset 9 (#1764238)
|
||||||
|
|
||||||
|
* Wed Nov 6 2019 Florian Weimer <fweimer@redhat.com> - 2.28-86
|
||||||
|
- aarch64: Support STO_AARCH64_VARIANT_PCS, DT_AARCH64_VARIANT_PCS (#1726638)
|
||||||
|
|
||||||
|
* Mon Nov 4 2019 DJ Delorie <dj@redhat.com> - 2.28-85
|
||||||
|
- Add more test-in-container support (#1747502)
|
||||||
|
|
||||||
|
* Fri Nov 1 2019 DJ Delorie <dj@redhat.com> - 2.28-84
|
||||||
|
- Fix calling getpwent after endpwent (#1747502)
|
||||||
|
|
||||||
|
* Fri Nov 1 2019 DJ Delorie <dj@redhat.com> - 2.28-83
|
||||||
|
- nptl: Avoid fork handler lock for async-signal-safe fork (#1746928)
|
||||||
|
|
||||||
|
* Thu Oct 31 2019 DJ Delorie <dj@redhat.com> - 2.28-82
|
||||||
|
- Call _dl_open_check after relocation (#1682954)
|
||||||
|
|
||||||
|
* Thu Oct 31 2019 Arjun Shankar <arjun@redhat.com> - 2.28-81
|
||||||
|
- Add malloc fastbin tunable (#1764218)
|
||||||
|
|
||||||
|
* Thu Oct 31 2019 Arjun Shankar <arjun@redhat.com> - 2.28-80
|
||||||
|
- Fix race condition in tst-clone3 and add a new ldconfig test,
|
||||||
|
tst-ldconfig-bad-aux-cache (#1764226)
|
||||||
|
|
||||||
|
* Thu Oct 31 2019 Arjun Shankar <arjun@redhat.com> - 2.28-79
|
||||||
|
- Remove unwanted whitespace from size lines and account for top chunk in
|
||||||
|
malloc_info output (#1735747)
|
||||||
|
|
||||||
|
* Wed Oct 30 2019 Arjun Shankar <arjun@redhat.com> - 2.28-78
|
||||||
|
- Enhance malloc tcache (#1746933)
|
||||||
|
|
||||||
|
* Tue Oct 29 2019 Patsy Griffin <patsy@redhat.com> - 2.28-77
|
||||||
|
- Don't define initgroups in nsswitch.conf (#1747505)
|
||||||
|
|
||||||
|
* Mon Oct 28 2019 Patsy Griffin <patsy@redhat.com> - 2.28-76
|
||||||
|
- libio: Remove codecvt vtable. (#1764241)
|
||||||
|
|
||||||
|
* Mon Oct 28 2019 Patsy Griffin <patsy@redhat.com> - 2.28-75
|
||||||
|
- Implement --preload option for the dynamic linker.(#1747453)
|
||||||
|
|
||||||
|
* Mon Oct 28 2019 Patsy Griffin <patsy@redhat.com> - 2.28-74
|
||||||
|
- Make nsswitch.conf more distribution friendly.
|
||||||
|
Improve nscd.conf comments. (#1747505)
|
||||||
|
|
||||||
|
* Fri Oct 25 2019 Patsy Griffin <patsy@redhat.com> - 2.28-73
|
||||||
|
- Update system call names list to Linux 5.3 (#1764234)
|
||||||
|
|
||||||
* Mon Jul 22 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-72
|
* Mon Jul 22 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-72
|
||||||
- Skip wide buffer handling for legacy stdio handles (#1722215)
|
- Skip wide buffer handling for legacy stdio handles (#1722215)
|
||||||
|
Loading…
Reference in New Issue
Block a user