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 00/14] implement RTLD_NORELOCATE api [BZ #30007]
Date: Thu, 18 May 2023 13:28:40 +0500	[thread overview]
Message-ID: <20230518082854.3903342-1-stsp2@yandex.ru> (raw)

RTLD_NORELOCATE api is a proposal that adds a fine-grained control
over the solib dynamic-load process. It allows the user to load the
solib to the particular address he needs, using the mapping type he
needs. The basic idea is that after loading the solib with RTLD_NORELOCATE
flag, the user can move an unrelocated object before relocating it.

The API consist of the following elements:

`RTLD_NORELOCATE' - new dlopen() flag.
It defers the relocation of an object, allowing to perform the
relocation later. Ctors are delayed, and are called immediately
after the relocation is done.
Relocation is performed upon the first dlsym() or dlrelocate()
call with the obtained handle. This flag doesn't delay the
load of an object deps, but their relocation and ctors are
delayed. This flag doesn't delay the LA_ACT_CONSISTENT audit event.


`int dlrelocate(void *handle)' - new function to perform the
object relocation if the RTLD_NORELOCATE flag was used. The object
itself and all of its dependencies are relocated.
Returns EINVAL if already relocated. This function may be omitted
even if RTLD_NORELOCATE was used, in which case the relocation will
be performed upon the first dlsym() call with the obtained handle,
but using dlrelocate() function allows to handle relocation errors
and run ctors before using the object's handle. If the function
returned success then ctors of an object and all of its deps were
called by it.
If it returned error other than EINVAL (EINVAL means object
already relocated), then relocation error happened and the
handle should be closed with dlclose().


`RTLD_DI_MAPINFO' - new dlinfo() request that fills in this structure:
typedef struct
{
  void *map_start;		/* Beginning of mapping containing address.  */
  size_t map_length;		/* Length of mapping.  */
  size_t map_align;		/* Alignment of mapping.  */
  int relocated;		/* Indicates whether an object was relocated. */
} Dl_mapinfo;

The user have to check the `relocated` member, and if it is 0
then the object can be moved to the new location. The new location
must be aligned according to the `map_aligned' member, which is
usually equal to a page size. One way to move a solib image is to
use mmap() for allocating a new memory mapping, then use memcpy()
to copy an image, and finally use munmap() to unmap the memory space
at an old location.
This request may fail if the used handle was not obtained from dlopen().


`int dlset_object_base(void *handle, void *addr)' - new function to
set the new base address of an unrelocated object, after it was moved.
Returns error if the object is already relocated. The base address
set by this function, will be used when relocation is performed.


`RTLD_DI_DEPLIST' is a new dlinfo() request that fills in this structure:
typedef struct
{
  void **deps;			/* Array of handles for the deps.  */
  unsigned int ndeps;		/* Number of entries in the list.  */
} Dl_deplist;

It is needed if the user wants to move also the dependencies of the
loaded solib. In this case he needs to traverse the `deps' array,
make RTLD_DI_MAPINFO dlinfo() request per each handle from an array,
find the object he needs by inspecting the filled-in Dl_mapinfo structure,
make sure this object is not relocated yet, and move it, calling
dlset_object_base() at the end.


Use-case.

Suppose you have a VM that runs a 32bit code. Suppose you wrote a
compatibility layer that allows to compile the old 32bit non-unix code
under linux, into the native 64bit shared libraries. But compiling is
not enough and some calls should still go to a VM. VM's memory is available
in a 4Gb window somewhere in a 64bit space. In order for the code under
VM to handle the calls from a 64bit solib, you need to make sure all
pointers, that may be passed as a call arguments, are within 32 bits.
Heap and stack are dealt with by a custom libc, but in order to use
pointers to .bss objects, we need to relocate the solib to the low 32bit
address. But that's not enough, because in order for that lib to be
visible to the code under VM, it must also be mirrored to the VM window
under the map_address = reloc_address+VM_window_start.

RTLD_NORELOCATE solves that problem by allowing the user to mmap the
shared memory into the low 32bit address space and move an object there.
He may want to do so for all the library deps as well (using RTLD_DI_DEPLIST),
or only with the ones he is interested in. Then he maps the shared memory
into the VM window and either calls dlrelocate() or just starts using the
solib, in which case it will be relocated on the first symbol lookup.

             reply	other threads:[~2023-05-18  8:29 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-18  8:28 Stas Sergeev [this message]
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 ` [PATCH 08/14] finalize elf segments on a relocation step Stas Sergeev
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
  -- strict thread matches above, loose matches on Subject: below --
2023-05-08 15:00 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] 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-1-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).