0

I have a ELF shared object (.so) file, loaded in memory. I've successfully resolved its dependencies and applied some of its relocations.

However, for some libraries that require thread-local storage (TLS), I have to:

  • Acquire a module ID.
  • Allocate a block in the Dynamic Thread Vector.
  • Relocate some addresses with the value of my module ID.

It seems that _dl_next_tls_modid is not visible to programs linked to libc, so I can't acquire a module id this way.

I know that the thread control block is located in a register, and I can access the TCB and the DTV there, but I don't know how to add my own entry inside it.

Is there any way I can register my own thread local storage block for my custom loaded library? Are there any glibc visible functions or variables that might point me to what I want?

Thanks in advance.

Update:

glibc seems to have some bookkeeping mechanism that is separate from the DTV array. So, although pushing some stuff and increasing its generation does not create a segmentation fault, glibc still does not respect the slot I've pushed and seems to overwrite it with some other library's memory, after it has been dlopened!

So how can I access this module count?

Update #2:

So many important things are stored in a symbol named _rtld_global. I have successfully used some hacks to access it on Ubuntu 64-bit, but I'd like to find a way to access the symbol's size and fields in a portable way. (At least portable between x86 and x86_64). I do not want to include the relevant headers, not only because they're LGPL-licensed, but also because they have a lot of hairy dependencies.

Update #3:

To those who think that I'm facing unnecessary problems:
I'm trying to load a .so file from memory, without using files of any kind (so no files or any "virtual" files). This is possible on Windows, and I believe that building some kind of simple loader from scratch is possible, and I've successfully loading several C++ libraries without any TLS.

As all Linux libraries with TLS have to register to a data structure in glibc in order to run properly, I believe this is the only way to solve my problem (by uncovering some hidden API, or by touching the data structures themselves).

The question I'm asking is still in the title. I need to manipulate the TLS storage of Linux applications using glibc. The other 2 updates below are some problems I've met while trying to answer the question in the title.

trungnt2910
  • 102
  • 2
  • 10
  • Your question appears to be a very good example of http://xyproblem.info – Employed Russian Sep 01 '21 at 03:14
  • @EmployedRussian To be honest, you're right. However, the community hasn't been kindly enough to address my X problem. Before asking this question, I've read through [this question](https://stackoverflow.com/questions/5053664/dlopen-from-memory), and its clones: [clone1](https://stackoverflow.com/questions/9016254/loading-so-files-from-memory), [clone2](https://stackoverflow.com/questions/25919859/is-there-a-way-to-load-a-linux-shared-library-into-a-specific-memory-location),... – trungnt2910 Sep 01 '21 at 10:41

1 Answers1

0

I believe that building some kind of simple loader from scratch is possible, and I've successfully loading several C++ libraries without any TLS.

I strongly suspect that "simple loader" is in fact impossible, and your belief that you've successfully done this for libraries without TLS is mistaken -- you just haven't found a corner case (of which there are likely many) where your simple loader fails to work.

In any case, your real problem is still under-specified. E.g. could you use modified GLIBC with dlopen_with_offset() in it?

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Well, thanks for your answer, but is it even possible, for a library to use another `glibc` to manipulate an app that uses its own vanilla `glibc`? – trungnt2910 Sep 01 '21 at 14:55