From: Stas Sergeev <stsp2@yandex.ru>
To: libc-alpha@sourceware.org
Cc: Stas Sergeev <stsp2@yandex.ru>
Subject: [PATCH 08/14] finalize elf segments on a relocation step
Date: Thu, 18 May 2023 13:28:48 +0500 [thread overview]
Message-ID: <20230518082854.3903342-9-stsp2@yandex.ru> (raw)
In-Reply-To: <20230518082854.3903342-1-stsp2@yandex.ru>
This is needed so that the segment finalization can be delayed,
together with the relocation process.
The test-suite was run on x86_64/64 and showed no regressions.
Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
elf/dl-close.c | 1 +
elf/dl-load.c | 33 ++++++++++++++++++++++-----------
elf/dl-load.h | 2 +-
elf/dl-map-segments.h | 7 ++++++-
elf/dl-open.c | 10 +++++++++-
include/link.h | 5 ++++-
6 files changed, 43 insertions(+), 15 deletions(-)
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 48ac3663ec..0640fc0bec 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -691,6 +691,7 @@ _dl_close_worker (struct link_map *map, bool force)
GL(dl_initfirst) = NULL;
free (imap->l_dlopen_args);
+ free (imap->l_loadcmds);
free (imap);
}
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 28e582fbdf..31514fca84 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -950,6 +950,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
int type;
/* Initialize to keep the compiler happy. */
const char *errstring = NULL;
+ struct loadcmd *loadcmds = NULL;
int errval = 0;
/* Get file information. To match the kernel behavior, do not fill
@@ -969,6 +970,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
lose_errno:
errval = errno;
lose:
+ if (loadcmds)
+ free (loadcmds);
/* The file might already be closed. */
if (fd != -1)
__close_nocancel (fd);
@@ -1080,18 +1083,23 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
}
}
- /* On most platforms presume that PT_GNU_STACK is absent and the stack is
- * executable. Other platforms default to a nonexecutable stack and don't
- * need PT_GNU_STACK to do so. */
- unsigned int stack_flags = DEFAULT_STACK_PERMS;
+ /* On most platforms presume that PT_GNU_STACK is absent and the stack is
+ * executable. Other platforms default to a nonexecutable stack and don't
+ * need PT_GNU_STACK to do so. */
+ unsigned int stack_flags = DEFAULT_STACK_PERMS;
{
/* Scan the program header table, collecting its load commands. */
- struct loadcmd loadcmds[l->l_phnum];
- size_t nloadcmds = 0;
+ #define nloadcmds l->l_nloadcmds
bool empty_dynamic = false;
ElfW(Addr) p_align_max = 0;
+ loadcmds = (struct loadcmd *) malloc (sizeof (struct loadcmd) * l->l_phnum);
+ if (loadcmds == NULL)
+ goto lose;
+ l->l_loadcmds = loadcmds;
+ nloadcmds = 0;
+
/* The struct is initialized to zero so this is not necessary:
l->l_ld = 0;
l->l_phdr = 0;
@@ -1225,8 +1233,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
}
/* Align all PT_LOAD segments to the maximum p_align. */
- for (size_t i = 0; i < nloadcmds; i++)
- loadcmds[i].mapalign = p_align_max;
+ l->l_map_align = p_align_max;
/* dlopen of an executable is not valid because it is not possible
to perform proper relocations, handle static TLS, or run the
@@ -1263,9 +1270,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
l->l_map_start = l->l_map_end = 0;
goto lose;
}
- errstring = _dl_finalize_segments (l, type, loadcmds, nloadcmds);
- if (__glibc_unlikely (errstring != NULL))
- goto lose;
+ /* dlopen()ed solibs are finalized on a relocation step. */
+ if (!(mode & __RTLD_DLOPEN))
+ {
+ errstring = _dl_finalize_segments (l, type, loadcmds, nloadcmds);
+ if (__glibc_unlikely (errstring != NULL))
+ goto lose;
+ }
}
if (l->l_ld != 0)
diff --git a/elf/dl-load.h b/elf/dl-load.h
index 61f5c4fadf..555eed176d 100644
--- a/elf/dl-load.h
+++ b/elf/dl-load.h
@@ -75,7 +75,7 @@ ELF_PREFERRED_ADDRESS_DATA;
Its details have been expanded out and converted. */
struct loadcmd
{
- ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign, maphole;
+ ElfW(Addr) mapstart, mapend, dataend, allocend, maphole;
ElfW(Off) mapoff;
int prot; /* PROT_* bits. */
};
diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index da6b762bca..a0078a77c8 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -100,7 +100,7 @@ _dl_map_segments (struct link_map *l, int fd,
- MAP_BASE_ADDR (l));
/* Remember which part of the address space this object uses. */
- l->l_map_start = _dl_map_segment (mappref, maplength, c->mapalign);
+ l->l_map_start = _dl_map_segment (mappref, maplength, l->l_map_align);
if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
@@ -150,6 +150,9 @@ _dl_finalize_segments (struct link_map *l, int type,
{
const struct loadcmd *c = loadcmds;
+ if (l->l_map_completed)
+ return NULL;
+
while (c < &loadcmds[nloadcmds])
{
ElfW(Addr) hole_start, hole_size;
@@ -234,5 +237,7 @@ _dl_finalize_segments (struct link_map *l, int type,
++c;
}
+ l->l_map_completed = 1;
+
return NULL;
}
diff --git a/elf/dl-open.c b/elf/dl-open.c
index e553403e8b..f1f2e8d3a4 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -40,7 +40,8 @@
#include <dl-dst.h>
#include <dl-prop.h>
-
+#include "dl-load.h"
+#include "dl-map-segments.h"
/* We must be careful not to leave us in an inconsistent state. Thus we
catch any error and re-raise it after cleaning up. */
@@ -543,6 +544,8 @@ do_reloc_1 (struct link_map *new, int mode, Lmid_t nsid, bool call_ctors)
for (unsigned int i = last; i-- > first; )
{
+ const char *errstring;
+
l = new->l_initfini[i];
if (l->l_real->l_relocated)
@@ -555,6 +558,11 @@ do_reloc_1 (struct link_map *new, int mode, Lmid_t nsid, bool call_ctors)
relocation_in_progress = 1;
}
+ errstring = _dl_finalize_segments (l, ET_DYN, l->l_loadcmds,
+ l->l_nloadcmds);
+ if (__glibc_unlikely (errstring != NULL))
+ _dl_signal_error (EINVAL, l->l_libname->name, NULL, errstring);
+
#ifdef SHARED
if (__glibc_unlikely (GLRO(dl_profile) != NULL))
{
diff --git a/include/link.h b/include/link.h
index 03b9f82715..fa16dfa337 100644
--- a/include/link.h
+++ b/include/link.h
@@ -179,6 +179,7 @@ struct link_map
} l_type:2;
unsigned int l_dt_relr_ref:1; /* Nonzero if GLIBC_ABI_DT_RELR is
referenced. */
+ unsigned int l_map_completed:1; /* Nonzero if object fully mapped. */
unsigned int l_relocated:1; /* Nonzero if object's relocations done. */
unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */
unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */
@@ -252,7 +253,7 @@ struct link_map
/* Start and finish of memory map for this object. l_map_start
need not be the same as l_addr. */
- ElfW(Addr) l_map_start, l_map_end;
+ ElfW(Addr) l_map_start, l_map_end, l_map_align;
/* End of the executable part of the mapping. */
ElfW(Addr) l_text_end;
@@ -349,6 +350,8 @@ struct link_map
unsigned long long int l_serial;
void *l_dlopen_args;
+ void *l_loadcmds;
+ size_t l_nloadcmds;
};
#include <dl-relocate-ld.h>
--
2.39.2
next prev parent reply other threads:[~2023-05-18 8:29 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-18 8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
2023-05-18 8:28 ` [PATCH 01/14] elf: switch _dl_map_segment() to anonymous mapping Stas Sergeev
2023-05-18 8:28 ` [PATCH 02/14] use initial mmap also for ET_EXEC Stas Sergeev
2023-05-18 8:28 ` [PATCH 03/14] rework maphole Stas Sergeev
2023-05-18 8:28 ` [PATCH 04/14] split do_reloc_1() from dl_open_worker_begin() Stas Sergeev
2023-05-18 8:28 ` [PATCH 05/14] split do_reloc_2() out of do_open_worker() Stas Sergeev
2023-05-18 8:28 ` [PATCH 06/14] move relocation into _dl_object_reloc() func Stas Sergeev
2023-05-18 8:28 ` [PATCH 07/14] split out _dl_finalize_segments() Stas Sergeev
2023-05-18 8:28 ` Stas Sergeev [this message]
2023-05-18 8:28 ` [PATCH 09/14] implement RTLD_NORELOCATE dlopen() flag Stas Sergeev
2023-05-18 8:28 ` [PATCH 10/14] add test-case for RTLD_NORELOCATE Stas Sergeev
2023-05-18 8:28 ` [PATCH 11/14] implement dlrelocate() function Stas Sergeev
2023-05-18 8:28 ` [PATCH 12/14] implement RTLD_DI_MAPINFO dlinfo() request Stas Sergeev
2023-05-18 8:28 ` [PATCH 13/14] implement dlset_object_base() function Stas Sergeev
2023-05-18 8:28 ` [PATCH 14/14] implement RTLD_DI_DEPLIST dlinfo() request Stas Sergeev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230518082854.3903342-9-stsp2@yandex.ru \
--to=stsp2@yandex.ru \
--cc=libc-alpha@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).