public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
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


  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).