Hi Zack, thanks for a reply. Have you forgot to CC the e-mail to me, or was it some spam filtering? Carlos have just told me about it. I'll use copy/paste from web interface to reply, and will monitor the web archive for a few days in case your mails to me are blocked somewhere. > Let me try to highlight specific issues from the feedback you've been > getting. It appears to me that your *API* proposal -- not any details > of its implementation, the API itself -- is unacceptable *BECAUSE*: > > * It introduces a callback from the dynamic loader into user code, that > is to be run with an internal lock held. glibc does already have > callbacks like that, but we do not want to introduce any more of > them, period. > * It assumes that the dynamic loader will always, in the future, operate > by creating a large initial mapping and then modifying protection > flags on it. Yes, those are the totally valid concerns raised by Szabolcs. They were very difficult to address actually, and eventually I came to this proposal: https://sourceware.org/pipermail/libc-alpha/2023-April/147243.html It is needed to address exactly those, but it may not be obvious yet how exactly they are related. I think this is not a problem, you'll see that in a next dlmem() draft. These problems will be solved. Most of dlmem() can be off-loaded to either proposed RTLD_NORELOC or something similar. > * It assumes that it the dynamic loader is, and will always be, capable > of taking a pointer to a block of memory -- no matter how it was > originally allocated -- and then chopping its virtual memory map up to > satisfy the requirements of the embedded ELF program header table, > without breaking anything else. I think you are talking about a premap callback here? It will be dropped per comment 1 of yours, so I think this is mostly a duplicate. > [On this specific note, I foresee > someone trying to write a dynamic module into memory allocated with > memalign() or even plain old malloc(); calling dlmem() on this is very > likely to apply PROT_NONE to address ranges containing malloc > metadata!] No-no, it never changes the protection of a source buffer! Nothing to worry about here. Also there are some recommendations in an API draft what mappings are supported as a source and what not - using memalign() space is very much unrecommended unless you know what you do (see api draft for details). But the protections are of course not altered. > For instance, maybe we could have an fdlopen variant that > called callback functions instead of mmap() and mprotect(). Unlike > your dlmem_premap_t, I think it ought to be possible to avoid doing > those specific operations with any locks held. But what such a callback would do? Plain read()? So. You are welcome to this lengthy thread. :) I am attaching an API draft in case you are curious about a details, but it was not yet updated to the removal of a callback. Sorry about that, just take my word on that for now. :) There are a few things that you miss about the proposed design (as every newcomer to this thread does), so let me show you an examples of fdlopen() and dlopen_with_offset() implemented on top of dlmem(). Most of things, like eg the source buffer usage, will be more clear after that: static void * fdlopen (int fd, int flags) {   off_t len;   void *addr;   void *handle;   len = lseek (fd, 0, SEEK_END);   lseek (fd, 0, SEEK_SET);   addr = mmap (NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);   if (addr == MAP_FAILED)     return NULL;   handle = dlmem (addr, len, flags, NULL);   munmap (addr, len);   return handle; } If we run that example, then in /proc/self/maps we will see the correct references to an elf file: $ LD_LIBRARY_PATH=..:. ./tst-dlmem-fdlopen unaligned buf gives buffer not aligned: Invalid argument 7fb413101000-7fb413102000 r--p 00000000 00:28 17195405 /home/stas/src/glibc-dev/build/dlfcn/glreflib1.so 7fb413102000-7fb413103000 r-xp 00001000 00:28 17195405 /home/stas/src/glibc-dev/build/dlfcn/glreflib1.so 7fb413103000-7fb413104000 r--p 00002000 00:28 17195405 /home/stas/src/glibc-dev/build/dlfcn/glreflib1.so 7fb413104000-7fb413105000 r--p 00002000 00:28 17195405 /home/stas/src/glibc-dev/build/dlfcn/glreflib1.so 7fb413105000-7fb413106000 rw-p 00003000 00:28 17195405 /home/stas/src/glibc-dev/build/dlfcn/glreflib1.so As you an see, there is no reference to the full file, just to the elf segments. That's because the above code just munmap()s the source buffer after dlmem() returns. Its protection was never changed. Now, dlopen_with_offset() is slightly more difficult, but is suggested for a read too: /* Load the shared library from a container file. file - file name. offset - solib offset within a container file. Highly recommended to be page-aligned. length - solib file length (not a container file length). flags - dlopen() flags. */ void *dlopen_with_offset4 (const char *file, off_t offset, size_t length, int flags) { void *addr; void *handle; int fd; off_t pad_size = (offset & (getpagesize () - 1)); off_t aligned_offset = offset - pad_size; size_t map_length = length + pad_size; fd = open (file, O_RDONLY); if (fd == -1) return NULL; addr = mmap (NULL, map_length, PROT_READ, MAP_PRIVATE, fd, aligned_offset); close(fd); if (addr == MAP_FAILED) return NULL; if (pad_size) { /* We need to fix alignment by hands. :-( And for that we need a shared mapping. */ void *addr2 = mmap (NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (addr2 == MAP_FAILED) { munmap (addr, map_length); return NULL; } memcpy (addr2, addr + pad_size, length); munmap (addr, map_length); addr = addr2; map_length = length; } handle = dlmem (addr, length, flags, NULL); munmap (addr, map_length); return handle; }