!473 回合上游社区补丁

From: @xujing99 
Reviewed-by: @liqingqing_1229 
Signed-off-by: @liqingqing_1229
This commit is contained in:
openeuler-ci-bot 2022-08-02 06:58:33 +00:00 committed by Gitee
commit e0b8d4f5a2
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
8 changed files with 1381 additions and 1 deletions

View File

@ -0,0 +1,34 @@
From 707efc2955a90299d8af8211756e2256fbc20c6e Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date: Wed, 6 Apr 2022 16:56:07 +0100
Subject: [PATCH] Remove _dl_skip_args_internal declaration
Conflict:NA
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=707efc2955a90299d8af8211756e2256fbc20c6e
It does not seem to be used.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
---
sysdeps/generic/ldsodefs.h | 5 -----
1 file changed, 5 deletions(-)
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 44750461a9..29f005499b 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -781,11 +781,6 @@ extern char **_dl_argv
rtld_hidden_proto (_dl_argv)
#if IS_IN (rtld)
extern unsigned int _dl_skip_args attribute_hidden
-# ifndef DL_ARGV_NOT_RELRO
- attribute_relro
-# endif
- ;
-extern unsigned int _dl_skip_args_internal attribute_hidden
# ifndef DL_ARGV_NOT_RELRO
attribute_relro
# endif
--
2.27.0

View File

@ -0,0 +1,188 @@
From 1da064c015dce624cb19fcdc0bace7af2bd8caec Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date: Thu, 30 Dec 2021 17:08:36 +0000
Subject: [PATCH 4/4] aarch64: Move ld.so _start to separate file and drop
_dl_skip_args
Conflict:NA
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=1da064c015dce624cb19fcdc0bace7af2bd8caec
A separate asm file is easier to maintain than a macro that expands to
inline asm.
The RTLD_START macro is only needed now because _dl_start is local in
rtld.c, but _start has to call it, if _dl_start was made hidden then it
could be empty.
_dl_skip_args is no longer needed.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
sysdeps/aarch64/Makefile | 1 +
sysdeps/aarch64/dl-machine.h | 77 +-----------------------------------
sysdeps/aarch64/dl-start.S | 53 +++++++++++++++++++++++++
3 files changed, 56 insertions(+), 75 deletions(-)
create mode 100644 sysdeps/aarch64/dl-start.S
diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
index 7183895d04..17fb1c5b72 100644
--- a/sysdeps/aarch64/Makefile
+++ b/sysdeps/aarch64/Makefile
@@ -33,6 +33,7 @@ tst-audit27-ENV = LD_AUDIT=$(objpfx)tst-auditmod27.so
endif
ifeq ($(subdir),elf)
+sysdep-rtld-routines += dl-start
sysdep-dl-routines += tlsdesc dl-tlsdesc
gen-as-const-headers += dl-link.sym
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
index b40050a981..fe120bb507 100644
--- a/sysdeps/aarch64/dl-machine.h
+++ b/sysdeps/aarch64/dl-machine.h
@@ -105,81 +105,8 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
return lazy;
}
-/* Initial entry point for the dynamic linker. The C function
- _dl_start is the real entry point, its return value is the user
- program's entry point */
-#ifdef __LP64__
-# define RTLD_START RTLD_START_1 ("x", "3", "sp")
-#else
-# define RTLD_START RTLD_START_1 ("w", "2", "wsp")
-#endif
-
-
-#define RTLD_START_1(PTR, PTR_SIZE_LOG, PTR_SP) asm ("\
-.text \n\
-.globl _start \n\
-.type _start, %function \n\
-.globl _dl_start_user \n\
-.type _dl_start_user, %function \n\
-_start: \n\
- // bti c \n\
- hint 34 \n\
- mov " PTR "0, " PTR_SP " \n\
- bl _dl_start \n\
- // returns user entry point in x0 \n\
- mov x21, x0 \n\
-_dl_start_user: \n\
- // get the original arg count \n\
- ldr " PTR "1, [sp] \n\
- // get the argv address \n\
- add " PTR "2, " PTR_SP ", #(1<<" PTR_SIZE_LOG ") \n\
- // get _dl_skip_args to see if we were \n\
- // invoked as an executable \n\
- adrp x4, _dl_skip_args \n\
- ldr w4, [x4, #:lo12:_dl_skip_args] \n\
- // do we need to adjust argc/argv \n\
- cmp w4, 0 \n\
- beq .L_done_stack_adjust \n\
- // subtract _dl_skip_args from original arg count \n\
- sub " PTR "1, " PTR "1, " PTR "4 \n\
- // store adjusted argc back to stack \n\
- str " PTR "1, [sp] \n\
- // find the first unskipped argument \n\
- mov " PTR "3, " PTR "2 \n\
- add " PTR "4, " PTR "2, " PTR "4, lsl #" PTR_SIZE_LOG " \n\
- // shuffle argv down \n\
-1: ldr " PTR "5, [x4], #(1<<" PTR_SIZE_LOG ") \n\
- str " PTR "5, [x3], #(1<<" PTR_SIZE_LOG ") \n\
- cmp " PTR "5, #0 \n\
- bne 1b \n\
- // shuffle envp down \n\
-1: ldr " PTR "5, [x4], #(1<<" PTR_SIZE_LOG ") \n\
- str " PTR "5, [x3], #(1<<" PTR_SIZE_LOG ") \n\
- cmp " PTR "5, #0 \n\
- bne 1b \n\
- // shuffle auxv down \n\
-1: ldp " PTR "0, " PTR "5, [x4, #(2<<" PTR_SIZE_LOG ")]! \n\
- stp " PTR "0, " PTR "5, [x3], #(2<<" PTR_SIZE_LOG ") \n\
- cmp " PTR "0, #0 \n\
- bne 1b \n\
- // Update _dl_argv \n\
- adrp x3, __GI__dl_argv \n\
- str " PTR "2, [x3, #:lo12:__GI__dl_argv] \n\
-.L_done_stack_adjust: \n\
- // compute envp \n\
- add " PTR "3, " PTR "2, " PTR "1, lsl #" PTR_SIZE_LOG " \n\
- add " PTR "3, " PTR "3, #(1<<" PTR_SIZE_LOG ") \n\
- adrp x16, _rtld_local \n\
- add " PTR "16, " PTR "16, #:lo12:_rtld_local \n\
- ldr " PTR "0, [x16] \n\
- bl _dl_init \n\
- // load the finalizer function \n\
- adrp x0, _dl_fini \n\
- add " PTR "0, " PTR "0, #:lo12:_dl_fini \n\
- // jump to the user_s entry point \n\
- mov x16, x21 \n\
- br x16 \n\
-");
+/* In elf/rtld.c _dl_start should be global so dl-start.S can reference it. */
+#define RTLD_START asm (".globl _dl_start");
#define elf_machine_type_class(type) \
((((type) == AARCH64_R(JUMP_SLOT) \
diff --git a/sysdeps/aarch64/dl-start.S b/sysdeps/aarch64/dl-start.S
new file mode 100644
index 0000000000..a3a57bd5a1
--- /dev/null
+++ b/sysdeps/aarch64/dl-start.S
@@ -0,0 +1,53 @@
+/* ld.so _start code.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+ENTRY (_start)
+ /* Create an initial frame with 0 LR and FP */
+ cfi_undefined (x30)
+ mov x29, #0
+ mov x30, #0
+
+ mov x0, sp
+ PTR_ARG (0)
+ bl _dl_start
+ /* Returns user entry point in x0. */
+ mov PTR_REG (21), PTR_REG (0)
+.globl _dl_start_user
+.type _dl_start_user, %function
+_dl_start_user:
+ /* Get argc. */
+ ldr PTR_REG (1), [sp]
+ /* Get argv. */
+ add x2, sp, PTR_SIZE
+ /* Compute envp. */
+ add PTR_REG (3), PTR_REG (2), PTR_REG (1), lsl PTR_LOG_SIZE
+ add PTR_REG (3), PTR_REG (3), PTR_SIZE
+ adrp x16, _rtld_local
+ add PTR_REG (16), PTR_REG (16), :lo12:_rtld_local
+ ldr PTR_REG (0), [x16]
+ bl _dl_init
+ /* Load the finalizer function. */
+ adrp x0, _dl_fini
+ add PTR_REG (0), PTR_REG (0), :lo12:_dl_fini
+ /* Jump to the user's entry point. */
+ mov x16, x21
+ br x16
+END (_start)
--
2.27.0

View File

@ -0,0 +1,400 @@
From 8dcb6d0af07fda3607b541857e4f3970a74ed55b Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Tue, 26 Apr 2022 14:23:02 +0200
Subject: [PATCH] dlfcn: Do not use rtld_active () to determine ld.so state
(bug 29078)
Conflict:adapt Makefile context
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=8dcb6d0af07fda3607b541857e4f3970a74ed55b
When audit modules are loaded, ld.so initialization is not yet
complete, and rtld_active () returns false even though ld.so is
mostly working. Instead, the static dlopen hook is used, but that
does not work at all because this is not a static dlopen situation.
Commit 466c1ea15f461edb8e3ffaf5d86d708876343bbf ("dlfcn: Rework
static dlopen hooks") moved the hook pointer into _rtld_global_ro,
which means that separate protection is not needed anymore and the
hook pointer can be checked directly.
The guard for disabling libio vtable hardening in _IO_vtable_check
should stay for now.
Fixes commit 8e1472d2c1e25e6eabc2059170731365f6d5b3d1 ("ld.so:
Examine GLRO to detect inactive loader [BZ #20204]").
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
dlfcn/dladdr.c | 2 +-
dlfcn/dladdr1.c | 2 +-
dlfcn/dlclose.c | 2 +-
dlfcn/dlerror.c | 2 +-
dlfcn/dlinfo.c | 2 +-
dlfcn/dlmopen.c | 2 +-
dlfcn/dlopen.c | 2 +-
dlfcn/dlopenold.c | 2 +-
dlfcn/dlsym.c | 2 +-
dlfcn/dlvsym.c | 2 +-
elf/Makefile | 6 +++
elf/dl-libc.c | 8 ++--
elf/tst-audit26.c | 35 +++++++++++++++
elf/tst-auditmod26.c | 104 +++++++++++++++++++++++++++++++++++++++++++
14 files changed, 159 insertions(+), 14 deletions(-)
create mode 100644 elf/tst-audit26.c
create mode 100644 elf/tst-auditmod26.c
diff --git a/dlfcn/dladdr.c b/dlfcn/dladdr.c
index ead117326f..d188d0e289 100644
--- a/dlfcn/dladdr.c
+++ b/dlfcn/dladdr.c
@@ -24,7 +24,7 @@ int
__dladdr (const void *address, Dl_info *info)
{
#ifdef SHARED
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dladdr (address, info);
#endif
return _dl_addr (address, info, NULL, NULL);
diff --git a/dlfcn/dladdr1.c b/dlfcn/dladdr1.c
index 5dadfd1220..e0c9526c90 100644
--- a/dlfcn/dladdr1.c
+++ b/dlfcn/dladdr1.c
@@ -24,7 +24,7 @@ int
__dladdr1 (const void *address, Dl_info *info, void **extra, int flags)
{
#ifdef SHARED
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dladdr1 (address, info, extra, flags);
#endif
diff --git a/dlfcn/dlclose.c b/dlfcn/dlclose.c
index a9921c3169..aab88c47fc 100644
--- a/dlfcn/dlclose.c
+++ b/dlfcn/dlclose.c
@@ -24,7 +24,7 @@ int
__dlclose (void *handle)
{
#ifdef SHARED
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dlclose (handle);
#endif
diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
index 3bf6049e3c..b899d252a1 100644
--- a/dlfcn/dlerror.c
+++ b/dlfcn/dlerror.c
@@ -32,7 +32,7 @@ char *
__dlerror (void)
{
# ifdef SHARED
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dlerror ();
# endif
diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c
index fc63c02681..068db5260c 100644
--- a/dlfcn/dlinfo.c
+++ b/dlfcn/dlinfo.c
@@ -89,7 +89,7 @@ dlinfo_implementation (void *handle, int request, void *arg)
int
___dlinfo (void *handle, int request, void *arg)
{
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dlinfo (handle, request, arg);
else
return dlinfo_implementation (handle, request, arg);
diff --git a/dlfcn/dlmopen.c b/dlfcn/dlmopen.c
index 2437f5ce22..b41778f16c 100644
--- a/dlfcn/dlmopen.c
+++ b/dlfcn/dlmopen.c
@@ -80,7 +80,7 @@ dlmopen_implementation (Lmid_t nsid, const char *file, int mode,
void *
___dlmopen (Lmid_t nsid, const char *file, int mode)
{
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dlmopen (nsid, file, mode, RETURN_ADDRESS (0));
else
return dlmopen_implementation (nsid, file, mode, RETURN_ADDRESS (0));
diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c
index 846ca38338..2696dde4b1 100644
--- a/dlfcn/dlopen.c
+++ b/dlfcn/dlopen.c
@@ -75,7 +75,7 @@ dlopen_implementation (const char *file, int mode, void *dl_caller)
void *
___dlopen (const char *file, int mode)
{
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dlopen (file, mode, RETURN_ADDRESS (0));
else
return dlopen_implementation (file, mode, RETURN_ADDRESS (0));
diff --git a/dlfcn/dlopenold.c b/dlfcn/dlopenold.c
index 67601434df..5c21a00496 100644
--- a/dlfcn/dlopenold.c
+++ b/dlfcn/dlopenold.c
@@ -70,7 +70,7 @@ __dlopen_nocheck (const char *file, int mode)
mode |= RTLD_LAZY;
args.mode = mode;
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dlopen (file, mode, RETURN_ADDRESS (0));
return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
diff --git a/dlfcn/dlsym.c b/dlfcn/dlsym.c
index a71f8ae247..2e9ff98e79 100644
--- a/dlfcn/dlsym.c
+++ b/dlfcn/dlsym.c
@@ -62,7 +62,7 @@ dlsym_implementation (void *handle, const char *name, void *dl_caller)
void *
___dlsym (void *handle, const char *name)
{
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dlsym (handle, name, RETURN_ADDRESS (0));
else
return dlsym_implementation (handle, name, RETURN_ADDRESS (0));
diff --git a/dlfcn/dlvsym.c b/dlfcn/dlvsym.c
index 72219d6da6..caa46ba1e0 100644
--- a/dlfcn/dlvsym.c
+++ b/dlfcn/dlvsym.c
@@ -65,7 +65,7 @@ dlvsym_implementation (void *handle, const char *name, const char *version,
void *
___dlvsym (void *handle, const char *name, const char *version)
{
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->dlvsym (handle, name, version,
RETURN_ADDRESS (0));
else
diff --git a/elf/Makefile b/elf/Makefile
index 8ed6c3b0b1..e4907d5de9 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -390,6 +390,7 @@ tests += \
tst-audit16 \
tst-audit17 \
tst-audit21 \
+ tst-audit26 \
tst-auditmany \
tst-auxobj \
tst-auxobj-dlopen \
@@ -767,6 +768,7 @@ modules-names = \
tst-auditmod12 \
tst-auditmod21a \
tst-auditmod21b \
+ tst-auditmod26 \
tst-auxvalmod \
tst-big-note-lib \
tst-deep1mod1 \
@@ -2286,6 +2288,10 @@ $(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \
$(objpfx)tst-auditmod21a.so: $(objpfx)tst-auditmod21b.so
tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so
+$(objpfx)tst-audit26.out: $(objpfx)tst-auditmod26.so
+$(objpfx)tst-auditmod26.so: $(libsupport)
+tst-audit26-ENV = LD_AUDIT=$(objpfx)tst-auditmod26.so
+
# tst-sonamemove links against an older implementation of the library.
LDFLAGS-tst-sonamemove-linkmod1.so = \
-Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index a7180d0af8..266e068da6 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -156,7 +156,7 @@ __libc_dlopen_mode (const char *name, int mode)
args.caller_dlopen = RETURN_ADDRESS (0);
#ifdef SHARED
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->libc_dlopen_mode (name, mode);
#endif
return dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map;
@@ -184,7 +184,7 @@ __libc_dlsym (void *map, const char *name)
args.name = name;
#ifdef SHARED
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->libc_dlsym (map, name);
#endif
return (dlerror_run (do_dlsym, &args) ? NULL
@@ -198,7 +198,7 @@ void *
__libc_dlvsym (void *map, const char *name, const char *version)
{
#ifdef SHARED
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->libc_dlvsym (map, name, version);
#endif
@@ -221,7 +221,7 @@ int
__libc_dlclose (void *map)
{
#ifdef SHARED
- if (!rtld_active ())
+ if (GLRO (dl_dlfcn_hook) != NULL)
return GLRO (dl_dlfcn_hook)->libc_dlclose (map);
#endif
return dlerror_run (do_dlclose, map);
diff --git a/elf/tst-audit26.c b/elf/tst-audit26.c
new file mode 100644
index 0000000000..3f920e83ba
--- /dev/null
+++ b/elf/tst-audit26.c
@@ -0,0 +1,35 @@
+/* Check the usability of <dlfcn.h> functions in audit modules.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <gnu/lib-names.h>
+
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+static int
+do_test (void)
+{
+ /* Check that the audit module has been loaded. */
+ void *handle = xdlopen ("mapped to libc", RTLD_LOCAL | RTLD_NOW);
+ TEST_VERIFY (handle
+ == xdlopen (LIBC_SO, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD));
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-auditmod26.c b/elf/tst-auditmod26.c
new file mode 100644
index 0000000000..db7ba95abe
--- /dev/null
+++ b/elf/tst-auditmod26.c
@@ -0,0 +1,104 @@
+/* Check the usability of <dlfcn.h> functions in audit modules. Audit module.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <first-versions.h>
+#include <gnu/lib-names.h>
+#include <link.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+unsigned int
+la_version (unsigned int current)
+{
+ /* Exercise various <dlfcn.h> functions. */
+
+ /* Check dlopen, dlsym, dlclose. */
+ void *handle = xdlopen (LIBM_SO, RTLD_LOCAL | RTLD_NOW);
+ void *ptr = xdlsym (handle, "sincos");
+ TEST_VERIFY (ptr != NULL);
+ ptr = dlsym (handle, "SINCOS");
+ TEST_VERIFY (ptr == NULL);
+ const char *message = dlerror ();
+ TEST_VERIFY (strstr (message, ": undefined symbol: SINCOS") != NULL);
+ ptr = dlsym (handle, "SINCOS");
+ TEST_VERIFY (ptr == NULL);
+ xdlclose (handle);
+ TEST_COMPARE_STRING (dlerror (), NULL);
+
+ handle = xdlopen (LIBC_SO, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD);
+
+ /* Check dlvsym. _exit is unlikely to gain another symbol
+ version. */
+ TEST_VERIFY (xdlsym (handle, "_exit")
+ == xdlvsym (handle, "_exit", FIRST_VERSION_libc__exit_STRING));
+
+ /* Check dlinfo. */
+ {
+ void *handle2 = NULL;
+ TEST_COMPARE (dlinfo (handle, RTLD_DI_LINKMAP, &handle2), 0);
+ TEST_VERIFY (handle2 == handle);
+ }
+
+ /* Check dladdr and dladdr1. */
+ Dl_info info = { };
+ TEST_VERIFY (dladdr (&_exit, &info) != 0);
+ if (strcmp (info.dli_sname, "_Exit") != 0) /* _Exit is an alias. */
+ TEST_COMPARE_STRING (info.dli_sname, "_exit");
+ TEST_VERIFY (info.dli_saddr == &_exit);
+ TEST_VERIFY (strstr (info.dli_fname, LIBC_SO));
+ void *extra_info;
+ memset (&info, 0, sizeof (info));
+ TEST_VERIFY (dladdr1 (&_exit, &info, &extra_info, RTLD_DL_LINKMAP) != 0);
+ TEST_VERIFY (extra_info == handle);
+
+ /* Verify that dlmopen creates a new namespace. */
+ void *dlmopen_handle = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
+ TEST_VERIFY (dlmopen_handle != handle);
+ memset (&info, 0, sizeof (info));
+ extra_info = NULL;
+ ptr = xdlsym (dlmopen_handle, "_exit");
+ TEST_VERIFY (dladdr1 (ptr, &info, &extra_info, RTLD_DL_LINKMAP) != 0);
+ TEST_VERIFY (extra_info == dlmopen_handle);
+ xdlclose (dlmopen_handle);
+
+ /* Terminate the process with an error state. This does not happen
+ automatically because the audit module state is not shared with
+ the main program. */
+ if (support_record_failure_is_failed ())
+ {
+ fflush (stdout);
+ fflush (stderr);
+ _exit (1);
+ }
+
+ return LAV_CURRENT;
+}
+
+char *
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
+{
+ if (strcmp (name, "mapped to libc") == 0)
+ return (char *) LIBC_SO;
+ else
+ return (char *) name;
+}
--
2.27.0

View File

@ -0,0 +1,30 @@
From c1ada668a381e122ee37cb8be7f0637111f63ea7 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Tue, 28 Jun 2022 10:40:16 +0200
Subject: [PATCH] elf: Fix -DNDEBUG warning in _dl_start_args_adjust
Conflict:NA
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=c1ada668a381e122ee37cb8be7f0637111f63ea7
This is another blocker for building glibc with the default
-Werror setting and -DNDEBUG.
---
elf/rtld.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/elf/rtld.c b/elf/rtld.c
index f5a3d1968f..cbbaf4a331 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1307,7 +1307,7 @@ _dl_start_args_adjust (int skip_args)
return;
/* Sanity check. */
- intptr_t argc = (intptr_t) sp[0] - skip_args;
+ intptr_t argc __attribute__ ((unused)) = (intptr_t) sp[0] - skip_args;
assert (argc == _dl_argc);
/* Adjust argc on stack. */
--
2.27.0

View File

@ -66,7 +66,7 @@
##############################################################################
Name: glibc
Version: 2.34
Release: 92
Release: 93
Summary: The GNU libc libraries
License: %{all_license}
URL: http://www.gnu.org/software/glibc/
@ -226,6 +226,13 @@ Patch138: Linux-Avoid-closing-1-on-failure-in-__closefrom_fall.patch
Patch139: Fix-deadlock-when-pthread_atfork-handler-calls-pthre.patch
Patch140: linux-Fix-mq_timereceive-check-for-32-bit-fallback-c.patch
Patch141: elf-Fix-compile-error-with-Werror-and-DNDEBUG.patch
Patch142: dlfcn-Do-not-use-rtld_active-to-determine-ld.so-stat.patch
Patch143: Remove-_dl_skip_args_internal-declaration.patch
Patch144: rtld-Use-generic-argv-adjustment-in-ld.so-BZ-23293.patch
Patch145: rtld-Remove-DL_ARGV_NOT_RELRO-and-make-_dl_skip_args.patch
Patch146: linux-Add-a-getauxval-test-BZ-23293.patch
Patch147: aarch64-Move-ld.so-_start-to-separate-file-and-drop-.patch
Patch148: elf-Fix-DNDEBUG-warning-in-_dl_start_args_adjust.patch
Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch
Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch
@ -1407,6 +1414,9 @@ fi
%endif
%changelog
* Mon Aug 1 2022 xujing <xujing125@huawei.com> - 2.34-93
- sync patches from upstream community
* Thu Jul 28 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-92
- optimize Obsoletes version

View File

@ -0,0 +1,114 @@
From 9faf5262c77487c96da8a3e961b88c0b1879e186 Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date: Tue, 3 May 2022 13:18:04 +0100
Subject: [PATCH 3/4] linux: Add a getauxval test [BZ #23293]
Conflict:adapt Makefile context
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=9faf5262c77487c96da8a3e961b88c0b1879e186
This is for bug 23293 and it relies on the glibc test system running
tests via explicit ld.so invokation by default.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
sysdeps/unix/sysv/linux/Makefile | 1 +
sysdeps/unix/sysv/linux/tst-getauxval.c | 74 +++++++++++++++++++++++++
2 files changed, 75 insertions(+)
create mode 100644 sysdeps/unix/sysv/linux/tst-getauxval.c
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index ca953804d0..89cb005c7d 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -126,6 +126,7 @@ tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
tst-close_range \
tst-prctl \
tst-scm_rights \
+ tst-getauxval \
# tests
# Test for the symbol version of fcntl that was replaced in glibc 2.28.
diff --git a/sysdeps/unix/sysv/linux/tst-getauxval.c b/sysdeps/unix/sysv/linux/tst-getauxval.c
new file mode 100644
index 0000000000..c4b6195743
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-getauxval.c
@@ -0,0 +1,74 @@
+/* Basic test for getauxval.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <sys/auxv.h>
+
+static int missing;
+static int mismatch;
+
+static void
+check_nonzero (unsigned long t, const char *s)
+{
+ unsigned long v = getauxval (t);
+ printf ("%s: %lu (0x%lx)\n", s, v, v);
+ if (v == 0)
+ missing++;
+}
+
+static void
+check_eq (unsigned long t, const char *s, unsigned long want)
+{
+ unsigned long v = getauxval (t);
+ printf ("%s: %lu want: %lu\n", s, v, want);
+ if (v != want)
+ mismatch++;
+}
+
+#define NZ(x) check_nonzero (x, #x)
+#define EQ(x, want) check_eq (x, #x, want)
+
+static int
+do_test (void)
+{
+ /* These auxv entries should be non-zero on Linux. */
+ NZ (AT_PHDR);
+ NZ (AT_PHENT);
+ NZ (AT_PHNUM);
+ NZ (AT_PAGESZ);
+ NZ (AT_ENTRY);
+ NZ (AT_CLKTCK);
+ NZ (AT_RANDOM);
+ NZ (AT_EXECFN);
+ if (missing)
+ FAIL_EXIT1 ("Found %d missing auxv entries.\n", missing);
+
+ /* Check against syscalls. */
+ EQ (AT_UID, getuid ());
+ EQ (AT_EUID, geteuid ());
+ EQ (AT_GID, getgid ());
+ EQ (AT_EGID, getegid ());
+ if (mismatch)
+ FAIL_EXIT1 ("Found %d mismatching auxv entries.\n", mismatch);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
--
2.27.0

View File

@ -0,0 +1,299 @@
From 86147bbeec25624cb26bb7646cdbc3a49bc56bf5 Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date: Tue, 3 May 2021 17:01:44 +0100
Subject: [PATCH 2/4] rtld: Remove DL_ARGV_NOT_RELRO and make _dl_skip_args
const
Conflict:adapt 2022 to 2021
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=86147bbeec25624cb26bb7646cdbc3a49bc56bf5
_dl_skip_args is always 0, so the target specific code that modifies
argv after relro protection is applied is no longer used.
After the patch relro protection is applied to _dl_argv consistently
on all targets.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
elf/rtld.c | 10 ++--------
sysdeps/aarch64/dl-sysdep.h | 4 ----
sysdeps/alpha/dl-sysdep.h | 23 -----------------------
sysdeps/arc/dl-sysdep.h | 4 ----
sysdeps/arm/dl-sysdep.h | 4 ----
sysdeps/csky/dl-sysdep.h | 23 -----------------------
sysdeps/generic/ldsodefs.h | 13 +++----------
sysdeps/ia64/dl-sysdep.h | 23 -----------------------
sysdeps/nios2/dl-sysdep.h | 4 ----
sysdeps/s390/s390-32/dl-sysdep.h | 23 -----------------------
sysdeps/sparc/dl-sysdep.h | 23 -----------------------
sysdeps/unix/sysv/linux/ia64/dl-sysdep.h | 4 ----
12 files changed, 5 insertions(+), 153 deletions(-)
delete mode 100644 sysdeps/alpha/dl-sysdep.h
delete mode 100644 sysdeps/csky/dl-sysdep.h
delete mode 100644 sysdeps/ia64/dl-sysdep.h
delete mode 100644 sysdeps/s390/s390-32/dl-sysdep.h
delete mode 100644 sysdeps/sparc/dl-sysdep.h
diff --git a/elf/rtld.c b/elf/rtld.c
index 6e8ed430e2..069940d73f 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -156,16 +156,10 @@ static void dl_main_state_init (struct dl_main_state *state);
extern char **_environ attribute_hidden;
static void process_envvars (struct dl_main_state *state);
-#ifdef DL_ARGV_NOT_RELRO
-int _dl_argc attribute_hidden;
-char **_dl_argv = NULL;
-/* Nonzero if we were run directly. */
-unsigned int _dl_skip_args attribute_hidden;
-#else
int _dl_argc attribute_relro attribute_hidden;
char **_dl_argv attribute_relro = NULL;
-unsigned int _dl_skip_args attribute_relro attribute_hidden;
-#endif
+/* Always 0, only kept for not-yet-updated target start code. */
+const unsigned int _dl_skip_args attribute_hidden;
rtld_hidden_data_def (_dl_argv)
#ifndef THREAD_SET_STACK_GUARD
diff --git a/sysdeps/aarch64/dl-sysdep.h b/sysdeps/aarch64/dl-sysdep.h
index 667786671c..1516dd7d3f 100644
--- a/sysdeps/aarch64/dl-sysdep.h
+++ b/sysdeps/aarch64/dl-sysdep.h
@@ -18,8 +18,4 @@
#include_next <dl-sysdep.h>
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
-
#define DL_EXTERN_PROTECTED_DATA
diff --git a/sysdeps/alpha/dl-sysdep.h b/sysdeps/alpha/dl-sysdep.h
deleted file mode 100644
index 3099ee419f..0000000000
--- a/sysdeps/alpha/dl-sysdep.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* System-specific settings for dynamic linker code. Alpha version.
- Copyright (C) 2002-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library. If not, see
- <https://www.gnu.org/licenses/>. */
-
-#include_next <dl-sysdep.h>
-
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
diff --git a/sysdeps/arc/dl-sysdep.h b/sysdeps/arc/dl-sysdep.h
index da060ceeee..cf4d160a73 100644
--- a/sysdeps/arc/dl-sysdep.h
+++ b/sysdeps/arc/dl-sysdep.h
@@ -18,8 +18,4 @@
#include_next <dl-sysdep.h>
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
-
#define DL_EXTERN_PROTECTED_DATA
diff --git a/sysdeps/arm/dl-sysdep.h b/sysdeps/arm/dl-sysdep.h
index ce7a84a7de..7a99107436 100644
--- a/sysdeps/arm/dl-sysdep.h
+++ b/sysdeps/arm/dl-sysdep.h
@@ -18,8 +18,4 @@
#include_next <dl-sysdep.h>
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
-
#define DL_EXTERN_PROTECTED_DATA
diff --git a/sysdeps/csky/dl-sysdep.h b/sysdeps/csky/dl-sysdep.h
deleted file mode 100644
index fc8a58b94c..0000000000
--- a/sysdeps/csky/dl-sysdep.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* System-specific settings for dynamic linker code. C-SKY version.
- Copyright (C) 2018-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library. If not, see
- <https://www.gnu.org/licenses/>. */
-
-#include_next <dl-sysdep.h>
-
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index b69ea2caeb..6716e1f382 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -753,18 +753,11 @@ rtld_hidden_proto (__libc_stack_end)
/* Parameters passed to the dynamic linker. */
extern int _dl_argc attribute_hidden attribute_relro;
-extern char **_dl_argv
-#ifndef DL_ARGV_NOT_RELRO
- attribute_relro
-#endif
- ;
+extern char **_dl_argv attribute_relro;
rtld_hidden_proto (_dl_argv)
#if IS_IN (rtld)
-extern unsigned int _dl_skip_args attribute_hidden
-# ifndef DL_ARGV_NOT_RELRO
- attribute_relro
-# endif
- ;
+/* Always 0, only kept for not-yet-updated target start code. */
+extern const unsigned int _dl_skip_args attribute_hidden;
#endif
#define rtld_progname _dl_argv[0]
diff --git a/sysdeps/ia64/dl-sysdep.h b/sysdeps/ia64/dl-sysdep.h
deleted file mode 100644
index e3a58bec24..0000000000
--- a/sysdeps/ia64/dl-sysdep.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* System-specific settings for dynamic linker code. IA-64 version.
- Copyright (C) 2002-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#include_next <dl-sysdep.h>
-
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
diff --git a/sysdeps/nios2/dl-sysdep.h b/sysdeps/nios2/dl-sysdep.h
index 0354650042..257b37c258 100644
--- a/sysdeps/nios2/dl-sysdep.h
+++ b/sysdeps/nios2/dl-sysdep.h
@@ -18,8 +18,4 @@
#include_next <dl-sysdep.h>
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
-
#define DL_EXTERN_PROTECTED_DATA
diff --git a/sysdeps/s390/s390-32/dl-sysdep.h b/sysdeps/s390/s390-32/dl-sysdep.h
deleted file mode 100644
index 699b50f156..0000000000
--- a/sysdeps/s390/s390-32/dl-sysdep.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* System-specific settings for dynamic linker code. S/390 version.
- Copyright (C) 2014-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library. If not, see
- <https://www.gnu.org/licenses/>. */
-
-#include_next <dl-sysdep.h>
-
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
diff --git a/sysdeps/sparc/dl-sysdep.h b/sysdeps/sparc/dl-sysdep.h
deleted file mode 100644
index f32f16a107..0000000000
--- a/sysdeps/sparc/dl-sysdep.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* System-specific settings for dynamic linker code. SPARC version.
- Copyright (C) 2002-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#include_next <dl-sysdep.h>
-
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
diff --git a/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h b/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
index 0d2a1d093a..aa1de6b361 100644
--- a/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
+++ b/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
@@ -48,8 +48,4 @@ extern int _dl_sysinfo_break attribute_hidden;
".previous");
#endif
-/* _dl_argv cannot be attribute_relro, because _dl_start_user
- might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
-
#endif /* dl-sysdep.h */
--
2.27.0

View File

@ -0,0 +1,305 @@
From ad43cac44a6860eaefcadadfb2acb349921e96bf Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date: Fri, 15 Jun 2018 16:14:58 +0100
Subject: [PATCH 1/4] rtld: Use generic argv adjustment in ld.so [BZ #23293]
Conflict:adapt rtld.c:1031 context
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=ad43cac44a6860eaefcadadfb2acb349921e96bf
When an executable is invoked as
./ld.so [ld.so-args] ./exe [exe-args]
then the argv is adujusted in ld.so before calling the entry point of
the executable so ld.so args are not visible to it. On most targets
this requires moving argv, env and auxv on the stack to ensure correct
stack alignment at the entry point. This had several issues:
- The code for this adjustment on the stack is written in asm as part
of the target specific ld.so _start code which is hard to maintain.
- The adjustment is done after _dl_start returns, where it's too late
to update GLRO(dl_auxv), as it is already readonly, so it points to
memory that was clobbered by the adjustment. This is bug 23293.
- _environ is also wrong in ld.so after the adjustment, but it is
likely not used after _dl_start returns so this is not user visible.
- _dl_argv was updated, but for this it was moved out of relro, which
changes security properties across targets unnecessarily.
This patch introduces a generic _dl_start_args_adjust function that
handles the argument adjustments after ld.so processed its own args
and before relro protection is applied.
The same algorithm is used on all targets, _dl_skip_args is now 0, so
existing target specific adjustment code is no longer used. The bug
affects aarch64, alpha, arc, arm, csky, ia64, nios2, s390-32 and sparc,
other targets don't need the change in principle, only for consistency.
The GNU Hurd start code relied on _dl_skip_args after dl_main returned,
now it checks directly if args were adjusted and fixes the Hurd startup
data accordingly.
Follow up patches can remove _dl_skip_args and DL_ARGV_NOT_RELRO.
Tested on aarch64-linux-gnu and cross tested on i686-gnu.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
elf/rtld.c | 73 ++++++++++++++++++++++++++++-------
sysdeps/mach/hurd/dl-sysdep.c | 30 +++++++-------
2 files changed, 73 insertions(+), 30 deletions(-)
diff --git a/elf/rtld.c b/elf/rtld.c
index 578fc14cdb..6e8ed430e2 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1301,6 +1301,62 @@ rtld_setup_main_map (struct link_map *main_map)
}
}
+/* Adjusts the contents of the stack and related globals for the user
+ entry point. The ld.so processed skip_args arguments and bumped
+ _dl_argv and _dl_argc accordingly. Those arguments are removed from
+ argv here. */
+static void
+_dl_start_args_adjust (int skip_args)
+{
+ void **sp = (void **) (_dl_argv - skip_args - 1);
+ void **p = sp + skip_args;
+
+ if (skip_args == 0)
+ return;
+
+ /* Sanity check. */
+ intptr_t argc = (intptr_t) sp[0] - skip_args;
+ assert (argc == _dl_argc);
+
+ /* Adjust argc on stack. */
+ sp[0] = (void *) (intptr_t) _dl_argc;
+
+ /* Update globals in rtld. */
+ _dl_argv -= skip_args;
+ _environ -= skip_args;
+
+ /* Shuffle argv down. */
+ do
+ *++sp = *++p;
+ while (*p != NULL);
+
+ assert (_environ == (char **) (sp + 1));
+
+ /* Shuffle envp down. */
+ do
+ *++sp = *++p;
+ while (*p != NULL);
+
+#ifdef HAVE_AUX_VECTOR
+ void **auxv = (void **) GLRO(dl_auxv) - skip_args;
+ GLRO(dl_auxv) = (ElfW(auxv_t) *) auxv; /* Aliasing violation. */
+ assert (auxv == sp + 1);
+
+ /* Shuffle auxv down. */
+ ElfW(auxv_t) ax;
+ char *oldp = (char *) (p + 1);
+ char *newp = (char *) (sp + 1);
+ do
+ {
+ memcpy (&ax, oldp, sizeof (ax));
+ memcpy (newp, &ax, sizeof (ax));
+ oldp += sizeof (ax);
+ newp += sizeof (ax);
+ }
+ while (ax.a_type != AT_NULL);
+#endif
+}
+
static void
dl_main (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
@@ -1354,6 +1410,7 @@ dl_main (const ElfW(Phdr) *phdr,
rtld_is_main = true;
char *argv0 = NULL;
+ char **orig_argv = _dl_argv;
/* Note the place where the dynamic linker actually came from. */
GL(dl_rtld_map).l_name = rtld_progname;
@@ -1368,7 +1425,6 @@ dl_main (const ElfW(Phdr) *phdr,
GLRO(dl_lazy) = -1;
}
- ++_dl_skip_args;
--_dl_argc;
++_dl_argv;
}
@@ -1377,14 +1433,12 @@ dl_main (const ElfW(Phdr) *phdr,
if (state.mode != rtld_mode_help)
state.mode = rtld_mode_verify;
- ++_dl_skip_args;
--_dl_argc;
++_dl_argv;
}
else if (! strcmp (_dl_argv[1], "--inhibit-cache"))
{
GLRO(dl_inhibit_cache) = 1;
- ++_dl_skip_args;
--_dl_argc;
++_dl_argv;
}
@@ -1394,7 +1448,6 @@ dl_main (const ElfW(Phdr) *phdr,
state.library_path = _dl_argv[2];
state.library_path_source = "--library-path";
- _dl_skip_args += 2;
_dl_argc -= 2;
_dl_argv += 2;
}
@@ -1403,7 +1456,6 @@ dl_main (const ElfW(Phdr) *phdr,
{
GLRO(dl_inhibit_rpath) = _dl_argv[2];
- _dl_skip_args += 2;
_dl_argc -= 2;
_dl_argv += 2;
}
@@ -1411,14 +1463,12 @@ dl_main (const ElfW(Phdr) *phdr,
{
audit_list_add_string (&state.audit_list, _dl_argv[2]);
- _dl_skip_args += 2;
_dl_argc -= 2;
_dl_argv += 2;
}
else if (! strcmp (_dl_argv[1], "--preload") && _dl_argc > 2)
{
state.preloadarg = _dl_argv[2];
- _dl_skip_args += 2;
_dl_argc -= 2;
_dl_argv += 2;
}
@@ -1426,7 +1476,6 @@ dl_main (const ElfW(Phdr) *phdr,
{
argv0 = _dl_argv[2];
- _dl_skip_args += 2;
_dl_argc -= 2;
_dl_argv += 2;
}
@@ -1434,7 +1483,6 @@ dl_main (const ElfW(Phdr) *phdr,
&& _dl_argc > 2)
{
state.glibc_hwcaps_prepend = _dl_argv[2];
- _dl_skip_args += 2;
_dl_argc -= 2;
_dl_argv += 2;
}
@@ -1442,7 +1490,6 @@ dl_main (const ElfW(Phdr) *phdr,
&& _dl_argc > 2)
{
state.glibc_hwcaps_mask = _dl_argv[2];
- _dl_skip_args += 2;
_dl_argc -= 2;
_dl_argv += 2;
}
@@ -1451,7 +1498,6 @@ dl_main (const ElfW(Phdr) *phdr,
{
state.mode = rtld_mode_list_tunables;
- ++_dl_skip_args;
--_dl_argc;
++_dl_argv;
}
@@ -1460,7 +1506,6 @@ dl_main (const ElfW(Phdr) *phdr,
{
state.mode = rtld_mode_list_diagnostics;
- ++_dl_skip_args;
--_dl_argc;
++_dl_argv;
}
@@ -1506,7 +1551,6 @@ dl_main (const ElfW(Phdr) *phdr,
_dl_usage (ld_so_name, NULL);
}
- ++_dl_skip_args;
--_dl_argc;
++_dl_argv;
@@ -1605,6 +1649,9 @@ dl_main (const ElfW(Phdr) *phdr,
/* Set the argv[0] string now that we've processed the executable. */
if (argv0 != NULL)
_dl_argv[0] = argv0;
+
+ /* Adjust arguments for the application entry point. */
+ _dl_start_args_adjust (_dl_argv - orig_argv);
}
else
{
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index 3cbe075615..8373962e62 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -76,6 +76,7 @@ _dl_sysdep_start (void **start_argptr,
{
void go (intptr_t *argdata)
{
+ char *orig_argv0;
char **p;
/* Cache the information in various global variables. */
@@ -84,6 +85,8 @@ _dl_sysdep_start (void **start_argptr,
_environ = &_dl_argv[_dl_argc + 1];
for (p = _environ; *p++;); /* Skip environ pointers and terminator. */
+ orig_argv0 = _dl_argv[0];
+
if ((void *) p == _dl_argv[0])
{
static struct hurd_startup_data nodata;
@@ -173,30 +176,23 @@ _dl_sysdep_start (void **start_argptr,
/* The call above might screw a few things up.
- First of all, if _dl_skip_args is nonzero, we are ignoring
- the first few arguments. However, if we have no Hurd startup
- data, it is the magical convention that ARGV[0] == P. The
+ P is the location after the terminating NULL of the list of
+ environment variables. It has to point to the Hurd startup
+ data or if that's missing then P == ARGV[0] must hold. The
startup code in init-first.c will get confused if this is not
the case, so we must rearrange things to make it so. We'll
- overwrite the origional ARGV[0] at P with ARGV[_dl_skip_args].
+ recompute P and move the Hurd data or the new ARGV[0] there.
- Secondly, if we need to be secure, it removes some dangerous
- environment variables. If we have no Hurd startup date this
- changes P (since that's the location after the terminating
- NULL in the list of environment variables). We do the same
- thing as in the first case but make sure we recalculate P.
- If we do have Hurd startup data, we have to move the data
- such that it starts just after the terminating NULL in the
- environment list.
+ Note: directly invoked ld.so can move arguments and env vars.
We use memmove, since the locations might overlap. */
- if (__libc_enable_secure || _dl_skip_args)
- {
- char **newp;
- for (newp = _environ; *newp++;);
+ char **newp;
+ for (newp = _environ; *newp++;);
- if (_dl_argv[-_dl_skip_args] == (char *) p)
+ if (newp != p || _dl_argv[0] != orig_argv0)
+ {
+ if (orig_argv0 == (char *) p)
{
if ((char *) newp != _dl_argv[0])
{
--
2.27.0