forked from rpms/glibc
import glibc-2.28-100.el8
This commit is contained in:
parent
0d6119401b
commit
ffa0667ada
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);
|
||||
|
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"
|
71
SOURCES/glibc-rh1717438.patch
Normal file
71
SOURCES/glibc-rh1717438.patch
Normal file
@ -0,0 +1,71 @@
|
||||
commit 11b451c8868d8a2b0edc5dfd44fc58d9ee538be0
|
||||
Author: Mark Wielaard <mark@klomp.org>
|
||||
Date: Wed May 15 17:14:01 2019 +0200
|
||||
|
||||
dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once) [BZ# 24476]
|
||||
|
||||
dlerror.c (__dlerror_main_freeres) will try to free resources which only
|
||||
have been initialized when init () has been called. That function is
|
||||
called when resources are needed using __libc_once (once, init) where
|
||||
once is a __libc_once_define (static, once) in the dlerror.c file.
|
||||
Trying to free those resources if init () hasn't been called will
|
||||
produce errors under valgrind memcheck. So guard the freeing of those
|
||||
resources using __libc_once_get (once) and make sure we have a valid
|
||||
key. Also add a similar guard to __dlerror ().
|
||||
|
||||
* dlfcn/dlerror.c (__dlerror_main_freeres): Guard using
|
||||
__libc_once_get (once) and static_bug == NULL.
|
||||
(__dlerror): Check we have a valid key, set result to static_buf
|
||||
otherwise.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
|
||||
index 96bf92533335036b..06732460ea1512cd 100644
|
||||
--- a/dlfcn/dlerror.c
|
||||
+++ b/dlfcn/dlerror.c
|
||||
@@ -72,9 +72,16 @@ __dlerror (void)
|
||||
__libc_once (once, init);
|
||||
|
||||
/* Get error string. */
|
||||
- result = (struct dl_action_result *) __libc_getspecific (key);
|
||||
- if (result == NULL)
|
||||
- result = &last_result;
|
||||
+ if (static_buf != NULL)
|
||||
+ result = static_buf;
|
||||
+ else
|
||||
+ {
|
||||
+ /* init () has been run and we don't use the static buffer.
|
||||
+ So we have a valid key. */
|
||||
+ result = (struct dl_action_result *) __libc_getspecific (key);
|
||||
+ if (result == NULL)
|
||||
+ result = &last_result;
|
||||
+ }
|
||||
|
||||
/* Test whether we already returned the string. */
|
||||
if (result->returned != 0)
|
||||
@@ -230,13 +237,19 @@ free_key_mem (void *mem)
|
||||
void
|
||||
__dlerror_main_freeres (void)
|
||||
{
|
||||
- void *mem;
|
||||
/* Free the global memory if used. */
|
||||
check_free (&last_result);
|
||||
- /* Free the TSD memory if used. */
|
||||
- mem = __libc_getspecific (key);
|
||||
- if (mem != NULL)
|
||||
- free_key_mem (mem);
|
||||
+
|
||||
+ if (__libc_once_get (once) && static_buf == NULL)
|
||||
+ {
|
||||
+ /* init () has been run and we don't use the static buffer.
|
||||
+ So we have a valid key. */
|
||||
+ void *mem;
|
||||
+ /* Free the TSD memory if used. */
|
||||
+ mem = __libc_getspecific (key);
|
||||
+ if (mem != NULL)
|
||||
+ free_key_mem (mem);
|
||||
+ }
|
||||
}
|
||||
|
||||
struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon));
|
186
SOURCES/glibc-rh1722215.patch
Normal file
186
SOURCES/glibc-rh1722215.patch
Normal file
@ -0,0 +1,186 @@
|
||||
commit 21cc130b78a4db9113fb6695e2b951e697662440
|
||||
Author: Dmitry V. Levin <ldv@altlinux.org>
|
||||
Date: Wed Feb 13 01:20:51 2019 +0000
|
||||
|
||||
libio: do not attempt to free wide buffers of legacy streams [BZ #24228]
|
||||
|
||||
Commit a601b74d31ca086de38441d316a3dee24c866305 aka glibc-2.23~693
|
||||
("In preparation for fixing BZ#16734, fix failure in misc/tst-error1-mem
|
||||
when _G_HAVE_MMAP is turned off.") introduced a regression:
|
||||
_IO_unbuffer_all now invokes _IO_wsetb to free wide buffers of all
|
||||
files, including legacy standard files which are small statically
|
||||
allocated objects that do not have wide buffers and the _mode member,
|
||||
causing memory corruption.
|
||||
|
||||
Another memory corruption in _IO_unbuffer_all happens when -1
|
||||
is assigned to the _mode member of legacy standard files that
|
||||
do not have it.
|
||||
|
||||
[BZ #24228]
|
||||
* libio/genops.c (_IO_unbuffer_all)
|
||||
[SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)]: Do not attempt to free wide
|
||||
buffers and access _IO_FILE_complete members of legacy libio streams.
|
||||
* libio/tst-bz24228.c: New file.
|
||||
* libio/tst-bz24228.map: Likewise.
|
||||
* libio/Makefile [build-shared] (tests): Add tst-bz24228.
|
||||
[build-shared] (generated): Add tst-bz24228.mtrace and
|
||||
tst-bz24228.check.
|
||||
[run-built-tests && build-shared] (tests-special): Add
|
||||
$(objpfx)tst-bz24228-mem.out.
|
||||
(LDFLAGS-tst-bz24228, tst-bz24228-ENV): New variables.
|
||||
($(objpfx)tst-bz24228-mem.out): New rule.
|
||||
|
||||
# Conflicts:
|
||||
# libio/Makefile
|
||||
|
||||
diff --git a/libio/Makefile b/libio/Makefile
|
||||
index cbfaf3832a45fc22..314e03d5ce72be2d 100644
|
||||
--- a/libio/Makefile
|
||||
+++ b/libio/Makefile
|
||||
@@ -73,6 +73,9 @@ ifeq (yes,$(build-shared))
|
||||
# Add test-fopenloc only if shared library is enabled since it depends on
|
||||
# shared localedata objects.
|
||||
tests += tst-fopenloc
|
||||
+# Add tst-bz24228 only if shared library is enabled since it can never meet its
|
||||
+# objective with static linking because the relevant code just is not there.
|
||||
+tests += tst-bz24228
|
||||
endif
|
||||
test-srcs = test-freopen
|
||||
|
||||
@@ -153,11 +156,14 @@ CFLAGS-oldtmpfile.c += -fexceptions
|
||||
|
||||
CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\"
|
||||
|
||||
+LDFLAGS-tst-bz24228 = -Wl,--version-script=tst-bz24228.map
|
||||
+
|
||||
tst_wprintf2-ARGS = "Some Text"
|
||||
|
||||
test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace
|
||||
tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace
|
||||
tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace
|
||||
+tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace
|
||||
|
||||
generated += test-fmemopen.mtrace test-fmemopen.check
|
||||
generated += tst-fopenloc.mtrace tst-fopenloc.check
|
||||
@@ -166,6 +172,7 @@ generated += tst-bz22415.mtrace tst-bz22415.check
|
||||
aux := fileops genops stdfiles stdio strops
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
+generated += tst-bz24228.mtrace tst-bz24228.check
|
||||
aux += oldfileops oldstdfiles
|
||||
endif
|
||||
|
||||
@@ -180,7 +187,8 @@ tests-special += $(objpfx)test-freopen.out $(objpfx)test-fmemopen-mem.out \
|
||||
ifeq (yes,$(build-shared))
|
||||
# Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared
|
||||
# library is enabled since they depend on tst-fopenloc.out.
|
||||
-tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
|
||||
+tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
|
||||
+ $(objpfx)tst-bz24228-mem.out
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -232,3 +240,7 @@ $(objpfx)tst-fopenloc-mem.out: $(objpfx)tst-fopenloc.out
|
||||
$(objpfx)tst-bz22415-mem.out: $(objpfx)tst-bz22415.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-bz22415.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
+
|
||||
+$(objpfx)tst-bz24228-mem.out: $(objpfx)tst-bz24228.out
|
||||
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-bz24228.mtrace > $@; \
|
||||
+ $(evaluate-test)
|
||||
diff --git a/libio/genops.c b/libio/genops.c
|
||||
index 2fec221b99729718..a8241dd26640bbcb 100644
|
||||
--- a/libio/genops.c
|
||||
+++ b/libio/genops.c
|
||||
@@ -789,9 +789,16 @@ _IO_unbuffer_all (void)
|
||||
|
||||
for (fp = (FILE *) _IO_list_all; fp; fp = fp->_chain)
|
||||
{
|
||||
+ int legacy = 0;
|
||||
+
|
||||
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
|
||||
+ if (__glibc_unlikely (_IO_vtable_offset (fp) != 0))
|
||||
+ legacy = 1;
|
||||
+#endif
|
||||
+
|
||||
if (! (fp->_flags & _IO_UNBUFFERED)
|
||||
/* Iff stream is un-orientated, it wasn't used. */
|
||||
- && fp->_mode != 0)
|
||||
+ && (legacy || fp->_mode != 0))
|
||||
{
|
||||
#ifdef _IO_MTSAFE_IO
|
||||
int cnt;
|
||||
@@ -805,7 +812,7 @@ _IO_unbuffer_all (void)
|
||||
__sched_yield ();
|
||||
#endif
|
||||
|
||||
- if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
|
||||
+ if (! legacy && ! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
|
||||
{
|
||||
fp->_flags |= _IO_USER_BUF;
|
||||
|
||||
@@ -816,7 +823,7 @@ _IO_unbuffer_all (void)
|
||||
|
||||
_IO_SETBUF (fp, NULL, 0);
|
||||
|
||||
- if (fp->_mode > 0)
|
||||
+ if (! legacy && fp->_mode > 0)
|
||||
_IO_wsetb (fp, NULL, NULL, 0);
|
||||
|
||||
#ifdef _IO_MTSAFE_IO
|
||||
@@ -827,7 +834,8 @@ _IO_unbuffer_all (void)
|
||||
|
||||
/* Make sure that never again the wide char functions can be
|
||||
used. */
|
||||
- fp->_mode = -1;
|
||||
+ if (! legacy)
|
||||
+ fp->_mode = -1;
|
||||
}
|
||||
|
||||
#ifdef _IO_MTSAFE_IO
|
||||
diff --git a/libio/tst-bz24228.c b/libio/tst-bz24228.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..6a74500d473ceeab
|
||||
--- /dev/null
|
||||
+++ b/libio/tst-bz24228.c
|
||||
@@ -0,0 +1,29 @@
|
||||
+/* BZ #24228 check for memory corruption in legacy libio
|
||||
+ 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 <mcheck.h>
|
||||
+#include <support/test-driver.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ mtrace ();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/libio/tst-bz24228.map b/libio/tst-bz24228.map
|
||||
new file mode 100644
|
||||
index 0000000000000000..4383e0817d7f5583
|
||||
--- /dev/null
|
||||
+++ b/libio/tst-bz24228.map
|
||||
@@ -0,0 +1,5 @@
|
||||
+# Hide the symbol from libc.so.6 to switch to the libio/oldfileops.c
|
||||
+# implementation when it is available for the architecture.
|
||||
+{
|
||||
+ local: _IO_stdin_used;
|
||||
+};
|
1013
SOURCES/glibc-rh1724975.patch
Normal file
1013
SOURCES/glibc-rh1724975.patch
Normal file
File diff suppressed because it is too large
Load Diff
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. */
|
||||
};
|
22
SOURCES/glibc-rh1727152.patch
Normal file
22
SOURCES/glibc-rh1727152.patch
Normal file
@ -0,0 +1,22 @@
|
||||
commit 61595e3d36ded374f97961503e843a314b0203c2
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Tue May 15 14:42:37 2018 +0200
|
||||
|
||||
nscd: avoid assertion failure during persistent db check
|
||||
|
||||
nscd should not abort when it finds inconsistencies in the persistent db.
|
||||
|
||||
diff --git a/nscd/connections.c b/nscd/connections.c
|
||||
index 47fbb9923aa2aac7..98182007646a33d5 100644
|
||||
--- a/nscd/connections.c
|
||||
+++ b/nscd/connections.c
|
||||
@@ -304,7 +304,8 @@ static int
|
||||
check_use (const char *data, nscd_ssize_t first_free, uint8_t *usemap,
|
||||
enum usekey use, ref_t start, size_t len)
|
||||
{
|
||||
- assert (len >= 2);
|
||||
+ if (len < 2)
|
||||
+ return 0;
|
||||
|
||||
if (start > first_free || start + len > first_free
|
||||
|| (start & BLOCK_ALIGN_M1))
|
221
SOURCES/glibc-rh1727241-1.patch
Normal file
221
SOURCES/glibc-rh1727241-1.patch
Normal file
@ -0,0 +1,221 @@
|
||||
commit 5e30b8ef0758763effa115634e0ed7d8938e4bc0
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jan 21 08:59:42 2019 +0100
|
||||
|
||||
resolv: Reformat inet_addr, inet_aton to GNU style
|
||||
|
||||
diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c
|
||||
index 022f7ea0841b6bae..32f58b0e13598b32 100644
|
||||
--- a/resolv/inet_addr.c
|
||||
+++ b/resolv/inet_addr.c
|
||||
@@ -1,3 +1,21 @@
|
||||
+/* Legacy IPv4 text-to-address functions.
|
||||
+ 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/>. */
|
||||
+
|
||||
/*
|
||||
* Copyright (c) 1983, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
@@ -78,105 +96,97 @@
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
-/*
|
||||
- * Ascii internet address interpretation routine.
|
||||
- * The value returned is in network order.
|
||||
- */
|
||||
+/* ASCII IPv4 Internet address interpretation routine. The value
|
||||
+ returned is in network order. */
|
||||
in_addr_t
|
||||
-__inet_addr(const char *cp) {
|
||||
- struct in_addr val;
|
||||
+__inet_addr (const char *cp)
|
||||
+{
|
||||
+ struct in_addr val;
|
||||
|
||||
- if (__inet_aton(cp, &val))
|
||||
- return (val.s_addr);
|
||||
- return (INADDR_NONE);
|
||||
+ if (__inet_aton (cp, &val))
|
||||
+ return val.s_addr;
|
||||
+ return INADDR_NONE;
|
||||
}
|
||||
weak_alias (__inet_addr, inet_addr)
|
||||
|
||||
-/*
|
||||
- * Check whether "cp" is a valid ascii representation
|
||||
- * of an Internet address and convert to a binary address.
|
||||
- * Returns 1 if the address is valid, 0 if not.
|
||||
- * This replaces inet_addr, the return value from which
|
||||
- * cannot distinguish between failure and a local broadcast address.
|
||||
- */
|
||||
+/* Check whether "cp" is a valid ASCII representation of an IPv4
|
||||
+ Internet address and convert it to a binary address. Returns 1 if
|
||||
+ the address is valid, 0 if not. This replaces inet_addr, the
|
||||
+ return value from which cannot distinguish between failure and a
|
||||
+ local broadcast address. */
|
||||
int
|
||||
-__inet_aton(const char *cp, struct in_addr *addr)
|
||||
+__inet_aton (const char *cp, struct in_addr *addr)
|
||||
{
|
||||
- static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
|
||||
- in_addr_t val;
|
||||
- char c;
|
||||
- union iaddr {
|
||||
- uint8_t bytes[4];
|
||||
- uint32_t word;
|
||||
- } res;
|
||||
- uint8_t *pp = res.bytes;
|
||||
- int digit;
|
||||
-
|
||||
- int saved_errno = errno;
|
||||
- __set_errno (0);
|
||||
-
|
||||
- res.word = 0;
|
||||
-
|
||||
- c = *cp;
|
||||
- for (;;) {
|
||||
- /*
|
||||
- * Collect number up to ``.''.
|
||||
- * Values are specified as for C:
|
||||
- * 0x=hex, 0=octal, isdigit=decimal.
|
||||
- */
|
||||
- if (!isdigit(c))
|
||||
- goto ret_0;
|
||||
- {
|
||||
- char *endp;
|
||||
- unsigned long ul = strtoul (cp, (char **) &endp, 0);
|
||||
- if (ul == ULONG_MAX && errno == ERANGE)
|
||||
- goto ret_0;
|
||||
- if (ul > 0xfffffffful)
|
||||
- goto ret_0;
|
||||
- val = ul;
|
||||
- digit = cp != endp;
|
||||
- cp = endp;
|
||||
- }
|
||||
- c = *cp;
|
||||
- if (c == '.') {
|
||||
- /*
|
||||
- * Internet format:
|
||||
- * a.b.c.d
|
||||
- * a.b.c (with c treated as 16 bits)
|
||||
- * a.b (with b treated as 24 bits)
|
||||
- */
|
||||
- if (pp > res.bytes + 2 || val > 0xff)
|
||||
- goto ret_0;
|
||||
- *pp++ = val;
|
||||
- c = *++cp;
|
||||
- } else
|
||||
- break;
|
||||
- }
|
||||
- /*
|
||||
- * Check for trailing characters.
|
||||
- */
|
||||
- if (c != '\0' && (!isascii(c) || !isspace(c)))
|
||||
- goto ret_0;
|
||||
- /*
|
||||
- * Did we get a valid digit?
|
||||
- */
|
||||
- if (!digit)
|
||||
- goto ret_0;
|
||||
-
|
||||
- /* Check whether the last part is in its limits depending on
|
||||
- the number of parts in total. */
|
||||
- if (val > max[pp - res.bytes])
|
||||
+ static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
|
||||
+ in_addr_t val;
|
||||
+ char c;
|
||||
+ union iaddr
|
||||
+ {
|
||||
+ uint8_t bytes[4];
|
||||
+ uint32_t word;
|
||||
+ } res;
|
||||
+ uint8_t *pp = res.bytes;
|
||||
+ int digit;
|
||||
+
|
||||
+ int saved_errno = errno;
|
||||
+ __set_errno (0);
|
||||
+
|
||||
+ res.word = 0;
|
||||
+
|
||||
+ c = *cp;
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ /* Collect number up to ``.''. Values are specified as for C:
|
||||
+ 0x=hex, 0=octal, isdigit=decimal. */
|
||||
+ if (!isdigit (c))
|
||||
+ goto ret_0;
|
||||
+ {
|
||||
+ char *endp;
|
||||
+ unsigned long ul = strtoul (cp, &endp, 0);
|
||||
+ if (ul == ULONG_MAX && errno == ERANGE)
|
||||
goto ret_0;
|
||||
-
|
||||
- if (addr != NULL)
|
||||
- addr->s_addr = res.word | htonl (val);
|
||||
-
|
||||
- __set_errno (saved_errno);
|
||||
- return (1);
|
||||
-
|
||||
-ret_0:
|
||||
- __set_errno (saved_errno);
|
||||
- return (0);
|
||||
+ if (ul > 0xfffffffful)
|
||||
+ goto ret_0;
|
||||
+ val = ul;
|
||||
+ digit = cp != endp;
|
||||
+ cp = endp;
|
||||
+ }
|
||||
+ c = *cp;
|
||||
+ if (c == '.')
|
||||
+ {
|
||||
+ /* Internet format:
|
||||
+ a.b.c.d
|
||||
+ a.b.c (with c treated as 16 bits)
|
||||
+ a.b (with b treated as 24 bits). */
|
||||
+ if (pp > res.bytes + 2 || val > 0xff)
|
||||
+ goto ret_0;
|
||||
+ *pp++ = val;
|
||||
+ c = *++cp;
|
||||
+ }
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+ /* Check for trailing characters. */
|
||||
+ if (c != '\0' && (!isascii (c) || !isspace (c)))
|
||||
+ goto ret_0;
|
||||
+ /* Did we get a valid digit? */
|
||||
+ if (!digit)
|
||||
+ goto ret_0;
|
||||
+
|
||||
+ /* Check whether the last part is in its limits depending on the
|
||||
+ number of parts in total. */
|
||||
+ if (val > max[pp - res.bytes])
|
||||
+ goto ret_0;
|
||||
+
|
||||
+ if (addr != NULL)
|
||||
+ addr->s_addr = res.word | htonl (val);
|
||||
+
|
||||
+ __set_errno (saved_errno);
|
||||
+ return 1;
|
||||
+
|
||||
+ ret_0:
|
||||
+ __set_errno (saved_errno);
|
||||
+ return 0;
|
||||
}
|
||||
weak_alias (__inet_aton, inet_aton)
|
||||
libc_hidden_def (__inet_aton)
|
80
SOURCES/glibc-rh1727241-2.patch
Normal file
80
SOURCES/glibc-rh1727241-2.patch
Normal file
@ -0,0 +1,80 @@
|
||||
commit 6ca53a2453598804a2559a548a08424fca96434a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jan 21 09:26:41 2019 +0100
|
||||
|
||||
resolv: Do not send queries for non-host-names in nss_dns [BZ #24112]
|
||||
|
||||
Before this commit, nss_dns would send a query which did not contain a
|
||||
host name as the query name (such as invalid\032name.example.com) and
|
||||
then reject the answer in getanswer_r and gaih_getanswer_slice, using
|
||||
a check based on res_hnok. With this commit, no query is sent, and a
|
||||
host-not-found error is returned to NSS without network interaction.
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 5dc2829cd148a568..99c3b61e1cee4d42 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -274,11 +274,26 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
return status;
|
||||
}
|
||||
|
||||
+/* Verify that the name looks like a host name. There is no point in
|
||||
+ sending a query which will not produce a usable name in the
|
||||
+ response. */
|
||||
+static enum nss_status
|
||||
+check_name (const char *name, int *h_errnop)
|
||||
+{
|
||||
+ if (res_hnok (name))
|
||||
+ return NSS_STATUS_SUCCESS;
|
||||
+ *h_errnop = HOST_NOT_FOUND;
|
||||
+ return NSS_STATUS_NOTFOUND;
|
||||
+}
|
||||
+
|
||||
enum nss_status
|
||||
_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
|
||||
char *buffer, size_t buflen, int *errnop,
|
||||
int *h_errnop)
|
||||
{
|
||||
+ enum nss_status status = check_name (name, h_errnop);
|
||||
+ if (status != NSS_STATUS_SUCCESS)
|
||||
+ return status;
|
||||
return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop,
|
||||
h_errnop, NULL, NULL);
|
||||
}
|
||||
@@ -289,6 +304,9 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
|
||||
char *buffer, size_t buflen, int *errnop,
|
||||
int *h_errnop)
|
||||
{
|
||||
+ enum nss_status status = check_name (name, h_errnop);
|
||||
+ if (status != NSS_STATUS_SUCCESS)
|
||||
+ return status;
|
||||
struct resolv_context *ctx = __resolv_context_get ();
|
||||
if (ctx == NULL)
|
||||
{
|
||||
@@ -296,7 +314,7 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
|
||||
*h_errnop = NETDB_INTERNAL;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- enum nss_status status = NSS_STATUS_NOTFOUND;
|
||||
+ status = NSS_STATUS_NOTFOUND;
|
||||
if (res_use_inet6 ())
|
||||
status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer,
|
||||
buflen, errnop, h_errnop, NULL, NULL);
|
||||
@@ -313,6 +331,9 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
char *buffer, size_t buflen, int *errnop,
|
||||
int *herrnop, int32_t *ttlp)
|
||||
{
|
||||
+ enum nss_status status = check_name (name, herrnop);
|
||||
+ if (status != NSS_STATUS_SUCCESS)
|
||||
+ return status;
|
||||
struct resolv_context *ctx = __resolv_context_get ();
|
||||
if (ctx == NULL)
|
||||
{
|
||||
@@ -347,7 +368,6 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
int ans2p_malloced = 0;
|
||||
|
||||
int olderr = errno;
|
||||
- enum nss_status status;
|
||||
int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
|
||||
host_buffer.buf->buf, 2048, &host_buffer.ptr,
|
||||
&ans2p, &nans2p, &resplen2, &ans2p_malloced);
|
698
SOURCES/glibc-rh1727241-3.patch
Normal file
698
SOURCES/glibc-rh1727241-3.patch
Normal file
@ -0,0 +1,698 @@
|
||||
commit 108bc4049f8ae82710aec26a92ffdb4b439c83fd
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jan 21 21:26:03 2019 +0100
|
||||
|
||||
CVE-2016-10739: getaddrinfo: Fully parse IPv4 address strings [BZ #20018]
|
||||
|
||||
The IPv4 address parser in the getaddrinfo function is changed so that
|
||||
it does not ignore trailing whitespace and all characters after it.
|
||||
For backwards compatibility, the getaddrinfo function still recognizes
|
||||
legacy name syntax, such as 192.000.002.010 interpreted as 192.0.2.8
|
||||
(octal).
|
||||
|
||||
This commit does not change the behavior of inet_addr and inet_aton.
|
||||
gethostbyname already had additional sanity checks (but is switched
|
||||
over to the new __inet_aton_exact function for completeness as well).
|
||||
|
||||
To avoid sending the problematic query names over DNS, commit
|
||||
6ca53a2453598804a2559a548a08424fca96434a ("resolv: Do not send queries
|
||||
for non-host-names in nss_dns [BZ #24112]") is needed.
|
||||
|
||||
diff --git a/include/arpa/inet.h b/include/arpa/inet.h
|
||||
index c3f28f2baaa2ed66..19aec74275069a45 100644
|
||||
--- a/include/arpa/inet.h
|
||||
+++ b/include/arpa/inet.h
|
||||
@@ -1,10 +1,10 @@
|
||||
#include <inet/arpa/inet.h>
|
||||
|
||||
#ifndef _ISOMAC
|
||||
-extern int __inet_aton (const char *__cp, struct in_addr *__inp);
|
||||
-libc_hidden_proto (__inet_aton)
|
||||
+/* Variant of inet_aton which rejects trailing garbage. */
|
||||
+extern int __inet_aton_exact (const char *__cp, struct in_addr *__inp);
|
||||
+libc_hidden_proto (__inet_aton_exact)
|
||||
|
||||
-libc_hidden_proto (inet_aton)
|
||||
libc_hidden_proto (inet_ntop)
|
||||
libc_hidden_proto (inet_pton)
|
||||
extern __typeof (inet_pton) __inet_pton;
|
||||
diff --git a/nscd/gai.c b/nscd/gai.c
|
||||
index 24bdfee1db3791e2..f57f396f574a6e52 100644
|
||||
--- a/nscd/gai.c
|
||||
+++ b/nscd/gai.c
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
/* This file uses the getaddrinfo code but it compiles it without NSCD
|
||||
support. We just need a few symbol renames. */
|
||||
-#define __inet_aton inet_aton
|
||||
#define __ioctl ioctl
|
||||
#define __getsockname getsockname
|
||||
#define __socket socket
|
||||
diff --git a/nscd/gethstbynm3_r.c b/nscd/gethstbynm3_r.c
|
||||
index 7beb9dce9f4b350c..f792c4fcd042d13d 100644
|
||||
--- a/nscd/gethstbynm3_r.c
|
||||
+++ b/nscd/gethstbynm3_r.c
|
||||
@@ -38,8 +38,6 @@
|
||||
#define HAVE_LOOKUP_BUFFER 1
|
||||
#define HAVE_AF 1
|
||||
|
||||
-#define __inet_aton inet_aton
|
||||
-
|
||||
/* We are nscd, so we don't want to be talking to ourselves. */
|
||||
#undef USE_NSCD
|
||||
|
||||
diff --git a/nss/digits_dots.c b/nss/digits_dots.c
|
||||
index 39bff38865a1ac5b..5441bce16ea8b2e9 100644
|
||||
--- a/nss/digits_dots.c
|
||||
+++ b/nss/digits_dots.c
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "nsswitch.h"
|
||||
|
||||
#ifdef USE_NSCD
|
||||
-# define inet_aton __inet_aton
|
||||
# include <nscd/nscd_proto.h>
|
||||
#endif
|
||||
|
||||
@@ -160,7 +159,7 @@ __nss_hostname_digits_dots_context (struct resolv_context *ctx,
|
||||
255.255.255.255? The test below will succeed
|
||||
spuriously... ??? */
|
||||
if (af == AF_INET)
|
||||
- ok = __inet_aton (name, (struct in_addr *) host_addr);
|
||||
+ ok = __inet_aton_exact (name, (struct in_addr *) host_addr);
|
||||
else
|
||||
{
|
||||
assert (af == AF_INET6);
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 56718654eeab85a3..72a0f196506ac489 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -34,6 +34,9 @@ routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
|
||||
tests = tst-aton tst-leaks tst-inet_ntop
|
||||
xtests = tst-leaks2
|
||||
|
||||
+tests-internal += tst-inet_aton_exact
|
||||
+
|
||||
+
|
||||
generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace
|
||||
|
||||
extra-libs := libresolv libnss_dns
|
||||
@@ -54,8 +57,10 @@ tests += \
|
||||
tst-resolv-binary \
|
||||
tst-resolv-edns \
|
||||
tst-resolv-network \
|
||||
+ tst-resolv-nondecimal \
|
||||
tst-resolv-res_init-multi \
|
||||
tst-resolv-search \
|
||||
+ tst-resolv-trailing \
|
||||
|
||||
# These tests need libdl.
|
||||
ifeq (yes,$(build-shared))
|
||||
@@ -190,9 +195,11 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
$(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-threads: \
|
||||
$(libdl) $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-canonname: \
|
||||
diff --git a/resolv/Versions b/resolv/Versions
|
||||
index b05778d9654aa0f2..9a82704af75f789b 100644
|
||||
--- a/resolv/Versions
|
||||
+++ b/resolv/Versions
|
||||
@@ -27,6 +27,7 @@ libc {
|
||||
__h_errno; __resp;
|
||||
|
||||
__res_iclose;
|
||||
+ __inet_aton_exact;
|
||||
__inet_pton_length;
|
||||
__resolv_context_get;
|
||||
__resolv_context_get_preinit;
|
||||
diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c
|
||||
index 32f58b0e13598b32..41b6166a5bd5a44b 100644
|
||||
--- a/resolv/inet_addr.c
|
||||
+++ b/resolv/inet_addr.c
|
||||
@@ -96,26 +96,14 @@
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
-/* ASCII IPv4 Internet address interpretation routine. The value
|
||||
- returned is in network order. */
|
||||
-in_addr_t
|
||||
-__inet_addr (const char *cp)
|
||||
-{
|
||||
- struct in_addr val;
|
||||
-
|
||||
- if (__inet_aton (cp, &val))
|
||||
- return val.s_addr;
|
||||
- return INADDR_NONE;
|
||||
-}
|
||||
-weak_alias (__inet_addr, inet_addr)
|
||||
-
|
||||
/* Check whether "cp" is a valid ASCII representation of an IPv4
|
||||
Internet address and convert it to a binary address. Returns 1 if
|
||||
the address is valid, 0 if not. This replaces inet_addr, the
|
||||
return value from which cannot distinguish between failure and a
|
||||
- local broadcast address. */
|
||||
-int
|
||||
-__inet_aton (const char *cp, struct in_addr *addr)
|
||||
+ local broadcast address. Write a pointer to the first
|
||||
+ non-converted character to *endp. */
|
||||
+static int
|
||||
+inet_aton_end (const char *cp, struct in_addr *addr, const char **endp)
|
||||
{
|
||||
static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
|
||||
in_addr_t val;
|
||||
@@ -180,6 +168,7 @@ __inet_aton (const char *cp, struct in_addr *addr)
|
||||
|
||||
if (addr != NULL)
|
||||
addr->s_addr = res.word | htonl (val);
|
||||
+ *endp = cp;
|
||||
|
||||
__set_errno (saved_errno);
|
||||
return 1;
|
||||
@@ -188,6 +177,41 @@ __inet_aton (const char *cp, struct in_addr *addr)
|
||||
__set_errno (saved_errno);
|
||||
return 0;
|
||||
}
|
||||
-weak_alias (__inet_aton, inet_aton)
|
||||
-libc_hidden_def (__inet_aton)
|
||||
-libc_hidden_weak (inet_aton)
|
||||
+
|
||||
+int
|
||||
+__inet_aton_exact (const char *cp, struct in_addr *addr)
|
||||
+{
|
||||
+ struct in_addr val;
|
||||
+ const char *endp;
|
||||
+ /* Check that inet_aton_end parsed the entire string. */
|
||||
+ if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0)
|
||||
+ {
|
||||
+ *addr = val;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ else
|
||||
+ return 0;
|
||||
+}
|
||||
+libc_hidden_def (__inet_aton_exact)
|
||||
+
|
||||
+/* inet_aton ignores trailing garbage. */
|
||||
+int
|
||||
+__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr)
|
||||
+{
|
||||
+ const char *endp;
|
||||
+ return inet_aton_end (cp, addr, &endp);
|
||||
+}
|
||||
+weak_alias (__inet_aton_ignore_trailing, inet_aton)
|
||||
+
|
||||
+/* ASCII IPv4 Internet address interpretation routine. The value
|
||||
+ returned is in network order. */
|
||||
+in_addr_t
|
||||
+__inet_addr (const char *cp)
|
||||
+{
|
||||
+ struct in_addr val;
|
||||
+ const char *endp;
|
||||
+ if (inet_aton_end (cp, &val, &endp))
|
||||
+ return val.s_addr;
|
||||
+ return INADDR_NONE;
|
||||
+}
|
||||
+weak_alias (__inet_addr, inet_addr)
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index f5e52cbbb9377762..94743a252e39d64a 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -399,8 +399,16 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
|
||||
cp = parser->buffer + sizeof ("nameserver") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
+
|
||||
+ /* Ignore trailing contents on the name server line. */
|
||||
+ {
|
||||
+ char *el;
|
||||
+ if ((el = strpbrk (cp, " \t\n")) != NULL)
|
||||
+ *el = '\0';
|
||||
+ }
|
||||
+
|
||||
struct sockaddr *sa;
|
||||
- if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a))
|
||||
+ if ((*cp != '\0') && (*cp != '\n') && __inet_aton_exact (cp, &a))
|
||||
{
|
||||
sa = allocate_address_v4 (a, NAMESERVER_PORT);
|
||||
if (sa == NULL)
|
||||
@@ -410,9 +418,6 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
|
||||
{
|
||||
struct in6_addr a6;
|
||||
char *el;
|
||||
-
|
||||
- if ((el = strpbrk (cp, " \t\n")) != NULL)
|
||||
- *el = '\0';
|
||||
if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL)
|
||||
*el = '\0';
|
||||
if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0))
|
||||
@@ -472,7 +477,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
|
||||
char separator = *cp;
|
||||
*cp = 0;
|
||||
struct resolv_sortlist_entry e;
|
||||
- if (__inet_aton (net, &a))
|
||||
+ if (__inet_aton_exact (net, &a))
|
||||
{
|
||||
e.addr = a;
|
||||
if (is_sort_mask (separator))
|
||||
@@ -484,7 +489,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
|
||||
cp++;
|
||||
separator = *cp;
|
||||
*cp = 0;
|
||||
- if (__inet_aton (net, &a))
|
||||
+ if (__inet_aton_exact (net, &a))
|
||||
e.mask = a.s_addr;
|
||||
else
|
||||
e.mask = net_mask (e.addr);
|
||||
diff --git a/resolv/tst-aton.c b/resolv/tst-aton.c
|
||||
index 08110a007af909ff..eb734d7758d6ed87 100644
|
||||
--- a/resolv/tst-aton.c
|
||||
+++ b/resolv/tst-aton.c
|
||||
@@ -1,11 +1,29 @@
|
||||
+/* Test legacy IPv4 text-to-address function inet_aton.
|
||||
+ Copyright (C) 1998-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 <array_length.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
-
|
||||
-static struct tests
|
||||
+static const struct tests
|
||||
{
|
||||
const char *input;
|
||||
int valid;
|
||||
@@ -16,6 +34,7 @@ static struct tests
|
||||
{ "-1", 0, 0 },
|
||||
{ "256", 1, 0x00000100 },
|
||||
{ "256.", 0, 0 },
|
||||
+ { "255a", 0, 0 },
|
||||
{ "256a", 0, 0 },
|
||||
{ "0x100", 1, 0x00000100 },
|
||||
{ "0200.0x123456", 1, 0x80123456 },
|
||||
@@ -40,7 +59,12 @@ static struct tests
|
||||
{ "1.2.256.4", 0, 0 },
|
||||
{ "1.2.3.0x100", 0, 0 },
|
||||
{ "323543357756889", 0, 0 },
|
||||
- { "10.1.2.3.4", 0, 0},
|
||||
+ { "10.1.2.3.4", 0, 0 },
|
||||
+ { "192.0.2.1", 1, 0xc0000201 },
|
||||
+ { "192.0.2.2\nX", 1, 0xc0000202 },
|
||||
+ { "192.0.2.3 Y", 1, 0xc0000203 },
|
||||
+ { "192.0.2.3Z", 0, 0 },
|
||||
+ { "192.000.002.010", 1, 0xc0000208 },
|
||||
};
|
||||
|
||||
|
||||
@@ -50,7 +74,7 @@ do_test (void)
|
||||
int result = 0;
|
||||
size_t cnt;
|
||||
|
||||
- for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt)
|
||||
+ for (cnt = 0; cnt < array_length (tests); ++cnt)
|
||||
{
|
||||
struct in_addr addr;
|
||||
|
||||
@@ -73,5 +97,4 @@ do_test (void)
|
||||
return result;
|
||||
}
|
||||
|
||||
-#define TEST_FUNCTION do_test ()
|
||||
-#include "../test-skeleton.c"
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/resolv/tst-inet_aton_exact.c b/resolv/tst-inet_aton_exact.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0fdfa3d6aa9aef91
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-inet_aton_exact.c
|
||||
@@ -0,0 +1,47 @@
|
||||
+/* Test internal legacy IPv4 text-to-address function __inet_aton_exact.
|
||||
+ 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 <arpa/inet.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct in_addr addr = { };
|
||||
+
|
||||
+ TEST_COMPARE (__inet_aton_exact ("192.0.2.1", &addr), 1);
|
||||
+ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000201);
|
||||
+
|
||||
+ TEST_COMPARE (__inet_aton_exact ("192.000.002.010", &addr), 1);
|
||||
+ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000208);
|
||||
+ TEST_COMPARE (__inet_aton_exact ("0xC0000234", &addr), 1);
|
||||
+ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000234);
|
||||
+
|
||||
+ /* Trailing content is not accepted. */
|
||||
+ TEST_COMPARE (__inet_aton_exact ("192.0.2.2X", &addr), 0);
|
||||
+ TEST_COMPARE (__inet_aton_exact ("192.0.2.3 Y", &addr), 0);
|
||||
+ TEST_COMPARE (__inet_aton_exact ("192.0.2.4\nZ", &addr), 0);
|
||||
+ TEST_COMPARE (__inet_aton_exact ("192.0.2.5\tT", &addr), 0);
|
||||
+ TEST_COMPARE (__inet_aton_exact ("192.0.2.6 Y", &addr), 0);
|
||||
+ TEST_COMPARE (__inet_aton_exact ("192.0.2.7\n", &addr), 0);
|
||||
+ TEST_COMPARE (__inet_aton_exact ("192.0.2.8\t", &addr), 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/resolv/tst-resolv-nondecimal.c b/resolv/tst-resolv-nondecimal.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..a0df6f332ae8faf7
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-nondecimal.c
|
||||
@@ -0,0 +1,139 @@
|
||||
+/* Test name resolution behavior for octal, hexadecimal IPv4 addresses.
|
||||
+ 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 <netdb.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ /* The tests are not supposed send any DNS queries. */
|
||||
+ FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+run_query_addrinfo (const char *query, const char *address)
|
||||
+{
|
||||
+ char *quoted_query = support_quote_string (query);
|
||||
+
|
||||
+ struct addrinfo *ai;
|
||||
+ struct addrinfo hints =
|
||||
+ {
|
||||
+ .ai_socktype = SOCK_STREAM,
|
||||
+ .ai_protocol = IPPROTO_TCP,
|
||||
+ };
|
||||
+
|
||||
+ char *context = xasprintf ("getaddrinfo \"%s\" AF_INET", quoted_query);
|
||||
+ char *expected = xasprintf ("address: STREAM/TCP %s 80\n", address);
|
||||
+ hints.ai_family = AF_INET;
|
||||
+ int ret = getaddrinfo (query, "80", &hints, &ai);
|
||||
+ check_addrinfo (context, ai, ret, expected);
|
||||
+ if (ret == 0)
|
||||
+ freeaddrinfo (ai);
|
||||
+ free (context);
|
||||
+
|
||||
+ context = xasprintf ("getaddrinfo \"%s\" AF_UNSPEC", quoted_query);
|
||||
+ hints.ai_family = AF_UNSPEC;
|
||||
+ ret = getaddrinfo (query, "80", &hints, &ai);
|
||||
+ check_addrinfo (context, ai, ret, expected);
|
||||
+ if (ret == 0)
|
||||
+ freeaddrinfo (ai);
|
||||
+ free (expected);
|
||||
+ free (context);
|
||||
+
|
||||
+ context = xasprintf ("getaddrinfo \"%s\" AF_INET6", quoted_query);
|
||||
+ expected = xasprintf ("flags: AI_V4MAPPED\n"
|
||||
+ "address: STREAM/TCP ::ffff:%s 80\n",
|
||||
+ address);
|
||||
+ hints.ai_family = AF_INET6;
|
||||
+ hints.ai_flags = AI_V4MAPPED;
|
||||
+ ret = getaddrinfo (query, "80", &hints, &ai);
|
||||
+ check_addrinfo (context, ai, ret, expected);
|
||||
+ if (ret == 0)
|
||||
+ freeaddrinfo (ai);
|
||||
+ free (expected);
|
||||
+ free (context);
|
||||
+
|
||||
+ free (quoted_query);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+run_query (const char *query, const char *address)
|
||||
+{
|
||||
+ char *quoted_query = support_quote_string (query);
|
||||
+ char *context = xasprintf ("gethostbyname (\"%s\")", quoted_query);
|
||||
+ char *expected = xasprintf ("name: %s\n"
|
||||
+ "address: %s\n", query, address);
|
||||
+ check_hostent (context, gethostbyname (query), expected);
|
||||
+ free (context);
|
||||
+
|
||||
+ context = xasprintf ("gethostbyname_r \"%s\"", quoted_query);
|
||||
+ struct hostent storage;
|
||||
+ char buf[4096];
|
||||
+ struct hostent *e = NULL;
|
||||
+ TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf),
|
||||
+ &e, &h_errno), 0);
|
||||
+ check_hostent (context, e, expected);
|
||||
+ free (context);
|
||||
+
|
||||
+ context = xasprintf ("gethostbyname2 (\"%s\", AF_INET)", quoted_query);
|
||||
+ check_hostent (context, gethostbyname2 (query, AF_INET), expected);
|
||||
+ free (context);
|
||||
+
|
||||
+ context = xasprintf ("gethostbyname2_r \"%s\" AF_INET", quoted_query);
|
||||
+ e = NULL;
|
||||
+ TEST_COMPARE (gethostbyname2_r (query, AF_INET, &storage, buf, sizeof (buf),
|
||||
+ &e, &h_errno), 0);
|
||||
+ check_hostent (context, e, expected);
|
||||
+ free (context);
|
||||
+ free (expected);
|
||||
+
|
||||
+ free (quoted_query);
|
||||
+
|
||||
+ /* The gethostbyname tests are always valid for getaddrinfo, but not
|
||||
+ vice versa. */
|
||||
+ run_query_addrinfo (query, address);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct resolv_test *aux = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response,
|
||||
+ });
|
||||
+
|
||||
+ run_query ("192.000.002.010", "192.0.2.8");
|
||||
+
|
||||
+ /* Hexadecimal numbers are not accepted by gethostbyname. */
|
||||
+ run_query_addrinfo ("0xc0000210", "192.0.2.16");
|
||||
+ run_query_addrinfo ("192.0x234", "192.0.2.52");
|
||||
+
|
||||
+ resolv_test_end (aux);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/resolv/tst-resolv-trailing.c b/resolv/tst-resolv-trailing.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..7504bdae572ed8d0
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-trailing.c
|
||||
@@ -0,0 +1,136 @@
|
||||
+/* Test name resolution behavior with trailing characters.
|
||||
+ 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 <array_length.h>
|
||||
+#include <netdb.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ /* The tests are not supposed send any DNS queries. */
|
||||
+ FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct resolv_test *aux = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response,
|
||||
+ });
|
||||
+
|
||||
+ static const char *const queries[] =
|
||||
+ {
|
||||
+ "192.0.2.1 ",
|
||||
+ "192.0.2.2\t",
|
||||
+ "192.0.2.3\n",
|
||||
+ "192.0.2.4 X",
|
||||
+ "192.0.2.5\tY",
|
||||
+ "192.0.2.6\nZ",
|
||||
+ "192.0.2. ",
|
||||
+ "192.0.2.\t",
|
||||
+ "192.0.2.\n",
|
||||
+ "192.0.2. X",
|
||||
+ "192.0.2.\tY",
|
||||
+ "192.0.2.\nZ",
|
||||
+ "2001:db8::1 ",
|
||||
+ "2001:db8::2\t",
|
||||
+ "2001:db8::3\n",
|
||||
+ "2001:db8::4 X",
|
||||
+ "2001:db8::5\tY",
|
||||
+ "2001:db8::6\nZ",
|
||||
+ };
|
||||
+ for (size_t query_idx = 0; query_idx < array_length (queries); ++query_idx)
|
||||
+ {
|
||||
+ const char *query = queries[query_idx];
|
||||
+ struct hostent storage;
|
||||
+ char buf[4096];
|
||||
+ struct hostent *e;
|
||||
+
|
||||
+ h_errno = 0;
|
||||
+ TEST_VERIFY (gethostbyname (query) == NULL);
|
||||
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND);
|
||||
+
|
||||
+ h_errno = 0;
|
||||
+ e = NULL;
|
||||
+ TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf),
|
||||
+ &e, &h_errno), 0);
|
||||
+ TEST_VERIFY (e == NULL);
|
||||
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND);
|
||||
+
|
||||
+ h_errno = 0;
|
||||
+ TEST_VERIFY (gethostbyname2 (query, AF_INET) == NULL);
|
||||
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND);
|
||||
+
|
||||
+ h_errno = 0;
|
||||
+ e = NULL;
|
||||
+ TEST_COMPARE (gethostbyname2_r (query, AF_INET,
|
||||
+ &storage, buf, sizeof (buf),
|
||||
+ &e, &h_errno), 0);
|
||||
+ TEST_VERIFY (e == NULL);
|
||||
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND);
|
||||
+
|
||||
+ h_errno = 0;
|
||||
+ TEST_VERIFY (gethostbyname2 (query, AF_INET6) == NULL);
|
||||
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND);
|
||||
+
|
||||
+ h_errno = 0;
|
||||
+ e = NULL;
|
||||
+ TEST_COMPARE (gethostbyname2_r (query, AF_INET6,
|
||||
+ &storage, buf, sizeof (buf),
|
||||
+ &e, &h_errno), 0);
|
||||
+ TEST_VERIFY (e == NULL);
|
||||
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND);
|
||||
+
|
||||
+ static const int gai_flags[] =
|
||||
+ {
|
||||
+ 0,
|
||||
+ AI_ADDRCONFIG,
|
||||
+ AI_NUMERICHOST,
|
||||
+ AI_IDN,
|
||||
+ AI_IDN | AI_NUMERICHOST,
|
||||
+ AI_V4MAPPED,
|
||||
+ AI_V4MAPPED | AI_NUMERICHOST,
|
||||
+ };
|
||||
+ for (size_t gai_flags_idx; gai_flags_idx < array_length (gai_flags);
|
||||
+ ++gai_flags_idx)
|
||||
+ {
|
||||
+ struct addrinfo hints = { .ai_flags = gai_flags[gai_flags_idx], };
|
||||
+ struct addrinfo *ai;
|
||||
+ hints.ai_family = AF_INET;
|
||||
+ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME);
|
||||
+ hints.ai_family = AF_INET6;
|
||||
+ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME);
|
||||
+ hints.ai_family = AF_UNSPEC;
|
||||
+ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME);
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ resolv_test_end (aux);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 00e0d94a8f5bb30d..6a5805c9e63a257c 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -488,7 +488,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
malloc_name = true;
|
||||
}
|
||||
|
||||
- if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
|
||||
+ if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0)
|
||||
{
|
||||
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
|
||||
at->family = AF_INET;
|
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
|
||||
|
88
SOURCES/glibc-rh1777241.patch
Normal file
88
SOURCES/glibc-rh1777241.patch
Normal file
@ -0,0 +1,88 @@
|
||||
commit bfdb731438206b0f70fe7afa890681155c30b419
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Wed Nov 27 12:35:40 2019 +0100
|
||||
|
||||
S390: Fix handling of needles crossing a page in strstr z15 ifunc-variant. [BZ #25226]
|
||||
|
||||
If the specified needle crosses a page-boundary, the s390-z15 ifunc variant of
|
||||
strstr truncates the needle which results in invalid results.
|
||||
|
||||
This is fixed by loading the needle beyond the page boundary to v18 instead of v16.
|
||||
The bug is sometimes observable in test-strstr.c in check1 and check2 as the
|
||||
haystack and needle is stored on stack. Thus the needle can be on a page boundary.
|
||||
|
||||
check2 is now extended to test haystack / needles located on stack, at end of page
|
||||
and on two pages.
|
||||
|
||||
This bug was introduced with commit 6f47401bd5fc71209219779a0426170a9a7395b0
|
||||
("S390: Add arch13 strstr ifunc variant.") and is already released in glibc 2.30.
|
||||
|
||||
diff --git a/string/test-strstr.c b/string/test-strstr.c
|
||||
index 5861b01b73e4c315..e9e14c1ee605516e 100644
|
||||
--- a/string/test-strstr.c
|
||||
+++ b/string/test-strstr.c
|
||||
@@ -138,16 +138,45 @@ check1 (void)
|
||||
static void
|
||||
check2 (void)
|
||||
{
|
||||
- const char s1[] = ", enable_static, \0, enable_shared, ";
|
||||
+ const char s1_stack[] = ", enable_static, \0, enable_shared, ";
|
||||
+ const size_t s1_byte_count = 18;
|
||||
+ const char *s2_stack = &(s1_stack[s1_byte_count]);
|
||||
+ const size_t s2_byte_count = 18;
|
||||
char *exp_result;
|
||||
- char *s2 = (void *) buf1 + page_size - 18;
|
||||
+ const size_t page_size_real = getpagesize ();
|
||||
|
||||
- strcpy (s2, s1);
|
||||
- exp_result = stupid_strstr (s1, s1 + 18);
|
||||
+ /* Haystack at end of page. The following page is protected. */
|
||||
+ char *s1_page_end = (void *) buf1 + page_size - s1_byte_count;
|
||||
+ strcpy (s1_page_end, s1_stack);
|
||||
+
|
||||
+ /* Haystack which crosses a page boundary.
|
||||
+ Note: page_size is at least 2 * getpagesize. See test_init. */
|
||||
+ char *s1_page_cross = (void *) buf1 + page_size_real - 8;
|
||||
+ strcpy (s1_page_cross, s1_stack);
|
||||
+
|
||||
+ /* Needle at end of page. The following page is protected. */
|
||||
+ char *s2_page_end = (void *) buf2 + page_size - s2_byte_count;
|
||||
+ strcpy (s2_page_end, s2_stack);
|
||||
+
|
||||
+ /* Needle which crosses a page boundary.
|
||||
+ Note: page_size is at least 2 * getpagesize. See test_init. */
|
||||
+ char *s2_page_cross = (void *) buf2 + page_size_real - 8;
|
||||
+ strcpy (s2_page_cross, s2_stack);
|
||||
+
|
||||
+ exp_result = stupid_strstr (s1_stack, s2_stack);
|
||||
FOR_EACH_IMPL (impl, 0)
|
||||
{
|
||||
- check_result (impl, s1, s1 + 18, exp_result);
|
||||
- check_result (impl, s2, s1 + 18, exp_result);
|
||||
+ check_result (impl, s1_stack, s2_stack, exp_result);
|
||||
+ check_result (impl, s1_stack, s2_page_end, exp_result);
|
||||
+ check_result (impl, s1_stack, s2_page_cross, exp_result);
|
||||
+
|
||||
+ check_result (impl, s1_page_end, s2_stack, exp_result);
|
||||
+ check_result (impl, s1_page_end, s2_page_end, exp_result);
|
||||
+ check_result (impl, s1_page_end, s2_page_cross, exp_result);
|
||||
+
|
||||
+ check_result (impl, s1_page_cross, s2_stack, exp_result);
|
||||
+ check_result (impl, s1_page_cross, s2_page_end, exp_result);
|
||||
+ check_result (impl, s1_page_cross, s2_page_cross, exp_result);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/s390/strstr-arch13.S b/sysdeps/s390/strstr-arch13.S
|
||||
index 929b026adfeba740..faa969849e09c2e1 100644
|
||||
--- a/sysdeps/s390/strstr-arch13.S
|
||||
+++ b/sysdeps/s390/strstr-arch13.S
|
||||
@@ -164,7 +164,7 @@ ENTRY(STRSTR_ARCH13)
|
||||
vfenezb %v19,%v18,%v18 /* Search zero in loaded needle bytes. */
|
||||
veclb %v19,%v21 /* Zero index <= max loaded byte index? */
|
||||
jle .Lneedle_loaded /* -> v18 contains full needle. */
|
||||
- vl %v16,0(%r3) /* Load needle beyond page boundary. */
|
||||
+ vl %v18,0(%r3) /* Load needle beyond page boundary. */
|
||||
vfenezb %v19,%v18,%v18
|
||||
j .Lneedle_loaded
|
||||
END(STRSTR_ARCH13)
|
@ -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
|
213
SPECS/glibc.spec
213
SPECS/glibc.spec
@ -1,6 +1,6 @@
|
||||
%define glibcsrcdir glibc-2.28
|
||||
%define glibcversion 2.28
|
||||
%define glibcrelease 66%{?dist}
|
||||
%define glibcrelease 100%{?dist}
|
||||
# Pre-release tarballs are pulled in from git using a command that is
|
||||
# effectively:
|
||||
#
|
||||
@ -121,7 +121,6 @@ URL: http://www.gnu.org/software/glibc/
|
||||
Source0: %{?glibc_release_url}%{glibcsrcdir}.tar.xz
|
||||
Source1: build-locale-archive.c
|
||||
Source4: nscd.conf
|
||||
Source7: nsswitch.conf
|
||||
Source8: power6emul.c
|
||||
Source9: bench.mk
|
||||
Source10: glibc-bench-compare
|
||||
@ -308,6 +307,93 @@ Patch173: glibc-rh1699194-1.patch
|
||||
Patch174: glibc-rh1699194-2.patch
|
||||
Patch175: glibc-rh1699194-3.patch
|
||||
Patch176: glibc-rh1699194-4.patch
|
||||
Patch177: glibc-rh1727241-1.patch
|
||||
Patch178: glibc-rh1727241-2.patch
|
||||
Patch179: glibc-rh1727241-3.patch
|
||||
Patch180: glibc-rh1717438.patch
|
||||
Patch181: glibc-rh1727152.patch
|
||||
Patch182: glibc-rh1724975.patch
|
||||
Patch183: glibc-rh1722215.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
|
||||
|
||||
##############################################################################
|
||||
# Continued list of core "glibc" package information:
|
||||
@ -1190,8 +1276,19 @@ $olddir/build-%{target}/elf/ld.so \
|
||||
$olddir/build-%{target}/locale/localedef \
|
||||
--prefix %{glibc_sysroot} --add-to-archive \
|
||||
eo *_*
|
||||
# Setup the locale-archive template for use by glibc-all-langpacks.
|
||||
mv locale-archive{,.tmpl}
|
||||
# Setup the locale-archive template for use by glibc-all-langpacks. We
|
||||
# copy the archive in place to keep the size of the file. Even though we
|
||||
# mark the file with "ghost" the size is used by rpm to compute the
|
||||
# required free space (see rhbz#1725131). We do this because there is a
|
||||
# point in the install when build-locale-archive has copied 100% of the
|
||||
# template into the new locale archive and so this consumes twice the
|
||||
# amount of diskspace. Note that this doesn't account for copying
|
||||
# existing compiled locales into the archive, this may consume even more
|
||||
# disk space and we can't fix that issue. In upstream we have moved away
|
||||
# from this process, removing build-locale-archive and installing a
|
||||
# default locale-archive without modification, and leaving compiled
|
||||
# locales as they are (without inclusion into the archive).
|
||||
cp locale-archive{,.tmpl}
|
||||
# Create the file lists for the language specific sub-packages:
|
||||
for i in eo *_*
|
||||
do
|
||||
@ -1219,7 +1316,7 @@ mv %{glibc_sysroot}%{_prefix}/lib/locale/*.filelist .
|
||||
# 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}
|
||||
# This is for ncsd - in glibc 2.2
|
||||
@ -1331,7 +1428,6 @@ rm -f %{glibc_sysroot}%{_infodir}/dir
|
||||
%endif
|
||||
|
||||
%ifnarch %{auxarches}
|
||||
truncate -s 0 %{glibc_sysroot}/%{_prefix}/lib/locale/locale-archive
|
||||
mkdir -p %{glibc_sysroot}/var/{db,run}/nscd
|
||||
touch %{glibc_sysroot}/var/{db,run}/nscd/{passwd,group,hosts,services}
|
||||
touch %{glibc_sysroot}/var/run/nscd/{socket,nscd.pid}
|
||||
@ -2184,6 +2280,111 @@ fi
|
||||
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
||||
|
||||
%changelog
|
||||
* 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
|
||||
- Skip wide buffer handling for legacy stdio handles (#1722215)
|
||||
|
||||
* Mon Jul 22 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-71
|
||||
- Remove copy_file_range emulation (#1724975)
|
||||
|
||||
* Mon Jul 22 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-70
|
||||
- Avoid nscd assertion failure during persistent db check (#1727152)
|
||||
|
||||
* Mon Jul 22 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-69
|
||||
- Fix invalid free under valgrind with libdl (#1717438)
|
||||
|
||||
* Thu Jul 18 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-68
|
||||
- Account for size of locale-archive in rpm package (#1725131)
|
||||
|
||||
* Thu Jul 18 2019 Carlos O'Donell <carlos@redhat.com> - 2.28-67
|
||||
- Reject IP addresses with trailing characters in getaddrinfo (#1727241)
|
||||
|
||||
* Fri Jun 14 2019 Florian Weimer <fweimer@redhat.com> - 2.28-66
|
||||
- Avoid header conflict between <sys/stat.h> and <linux/stat.h> (#1699194)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user