mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] [PATCH 1/4] ldso: add option to rewrite the argv block
@ 2020-03-29  0:19 rcombs
  2020-03-29  0:19 ` [musl] [PATCH 2/4] ldso: when run via CLI, set auxv as if the app was loaded by the kernel rcombs
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: rcombs @ 2020-03-29  0:19 UTC (permalink / raw)
  To: musl

---
 ldso/dynlink.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 6468f20..c378f00 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -1698,6 +1698,7 @@ void __dls3(size_t *sp, size_t *auxv)
 	char **argv = (void *)(sp+1);
 	char **argv_orig = argv;
 	char **envp = argv+argc+1;
+	int replace_argv = 0;
 
 	/* Find aux vector just past environ[] and use it to initialize
 	 * global data that may be needed before we can make syscalls. */
@@ -1771,6 +1772,8 @@ void __dls3(size_t *sp, size_t *auxv)
 				if (opt[5]=='=') replace_argv0 = opt+6;
 				else if (opt[5]) *argv = 0;
 				else if (*argv) replace_argv0 = *argv++;
+			} else if (!memcmp(opt, "replace-argv", 12)) {
+				replace_argv = 1;
 			} else {
 				argv[0] = 0;
 			}
@@ -1949,6 +1952,22 @@ void __dls3(size_t *sp, size_t *auxv)
 	debug.state = 0;
 	_dl_debug_state();
 
+	if (replace_argv) {
+		char *argv_end = argv_orig[0];
+		char *orig_ptr = argv_orig[0];
+		int i;
+		for (i = 0; i < (int)(argc - (argv-argv_orig)); i++) {
+			char *src = (i == 0 && replace_argv0) ? replace_argv0 : argv[i];
+			int len = strlen(src) + 1;
+			memmove(orig_ptr, src, len);
+			argv_end = argv[i] + strlen(argv[i]);
+			argv[i] = orig_ptr;
+			orig_ptr += len;
+		}
+		for (; orig_ptr < argv_end; orig_ptr++)
+			*orig_ptr = 0;
+	}
+
 	if (replace_argv0) argv[0] = replace_argv0;
 
 	errno = 0;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [musl] [PATCH 2/4] ldso: when run via CLI, set auxv as if the app was loaded by the kernel
  2020-03-29  0:19 [musl] [PATCH 1/4] ldso: add option to rewrite the argv block rcombs
@ 2020-03-29  0:19 ` rcombs
  2020-03-29  0:19 ` [musl] [PATCH 3/4] ldso: move (un)map_library functions to separate file rcombs
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: rcombs @ 2020-03-29  0:19 UTC (permalink / raw)
  To: musl

---
 ldso/dynlink.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index c378f00..5f637fd 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -1811,6 +1811,22 @@ void __dls3(size_t *sp, size_t *auxv)
 			}
 			dprintf(1, "\t%s (%p)\n", ldso.name, ldso.base);
 		}
+
+		// Make it look to the app as if it was loaded by the kernel
+		for (i=0; auxv[i]; i+=2) {
+			if (auxv[i] == AT_BASE)
+				auxv[i + 1] = (size_t)ldso.base;
+			if (auxv[i] == AT_PHDR)
+				auxv[i + 1] = (size_t)app.phdr;
+			if (auxv[i] == AT_ENTRY)
+				auxv[i + 1] = aux[AT_ENTRY];
+			if (auxv[i] == AT_PHNUM)
+				auxv[i + 1] = app.phnum;
+			if (auxv[i] == AT_PHENT)
+				auxv[i + 1] = app.phentsize;
+			if (auxv[i] == AT_EXECFN)
+				auxv[i + 1] = (size_t)app.name;
+		}
 	}
 	if (app.tls.size) {
 		libc.tls_head = tls_tail = &app.tls;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [musl] [PATCH 3/4] ldso: move (un)map_library functions to separate file
  2020-03-29  0:19 [musl] [PATCH 1/4] ldso: add option to rewrite the argv block rcombs
  2020-03-29  0:19 ` [musl] [PATCH 2/4] ldso: when run via CLI, set auxv as if the app was loaded by the kernel rcombs
@ 2020-03-29  0:19 ` rcombs
  2020-03-29  3:07   ` Rich Felker
  2020-03-29  0:19 ` [musl] [PATCH 4/4] crt: add dcrt1, with support for locating the dynamic loader at runtime rcombs
  2020-03-29  2:54 ` [musl] [PATCH 1/4] ldso: add option to rewrite the argv block Rich Felker
  3 siblings, 1 reply; 6+ messages in thread
From: rcombs @ 2020-03-29  0:19 UTC (permalink / raw)
  To: musl

---
 ldso/dynlink.c     | 270 +--------------------------------------------------
 ldso/map_library.h | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 278 insertions(+), 268 deletions(-)
 create mode 100644 ldso/map_library.h

diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 5f637fd..0e557b1 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -154,6 +154,8 @@ extern hidden void (*const __init_array_end)(void), (*const __fini_array_end)(vo
 weak_alias(__init_array_start, __init_array_end);
 weak_alias(__fini_array_start, __fini_array_end);
 
+#include "map_library.h"
+
 static int dl_strcmp(const char *l, const char *r)
 {
 	for (; *l==*r && *l; l++, r++);
@@ -161,44 +163,6 @@ static int dl_strcmp(const char *l, const char *r)
 }
 #define strcmp(l,r) dl_strcmp(l,r)
 
-/* Compute load address for a virtual address in a given dso. */
-#if DL_FDPIC
-static void *laddr(const struct dso *p, size_t v)
-{
-	size_t j=0;
-	if (!p->loadmap) return p->base + v;
-	for (j=0; v-p->loadmap->segs[j].p_vaddr >= p->loadmap->segs[j].p_memsz; j++);
-	return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
-}
-static void *laddr_pg(const struct dso *p, size_t v)
-{
-	size_t j=0;
-	size_t pgsz = PAGE_SIZE;
-	if (!p->loadmap) return p->base + v;
-	for (j=0; ; j++) {
-		size_t a = p->loadmap->segs[j].p_vaddr;
-		size_t b = a + p->loadmap->segs[j].p_memsz;
-		a &= -pgsz;
-		b += pgsz-1;
-		b &= -pgsz;
-		if (v-a<b-a) break;
-	}
-	return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
-}
-static void (*fdbarrier(void *p))()
-{
-	void (*fd)();
-	__asm__("" : "=r"(fd) : "0"(p));
-	return fd;
-}
-#define fpaddr(p, v) fdbarrier((&(struct funcdesc){ \
-	laddr(p, v), (p)->got }))
-#else
-#define laddr(p, v) (void *)((p)->base + (v))
-#define laddr_pg(p, v) laddr(p, v)
-#define fpaddr(p, v) ((void (*)())laddr(p, v))
-#endif
-
 static void decode_vec(size_t *v, size_t *a, size_t cnt)
 {
 	size_t i;
@@ -557,236 +521,6 @@ static void reclaim_gaps(struct dso *dso)
 	}
 }
 
-static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off)
-{
-	static int no_map_fixed;
-	char *q;
-	if (!no_map_fixed) {
-		q = mmap(p, n, prot, flags|MAP_FIXED, fd, off);
-		if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL)
-			return q;
-		no_map_fixed = 1;
-	}
-	/* Fallbacks for MAP_FIXED failure on NOMMU kernels. */
-	if (flags & MAP_ANONYMOUS) {
-		memset(p, 0, n);
-		return p;
-	}
-	ssize_t r;
-	if (lseek(fd, off, SEEK_SET) < 0) return MAP_FAILED;
-	for (q=p; n; q+=r, off+=r, n-=r) {
-		r = read(fd, q, n);
-		if (r < 0 && errno != EINTR) return MAP_FAILED;
-		if (!r) {
-			memset(q, 0, n);
-			break;
-		}
-	}
-	return p;
-}
-
-static void unmap_library(struct dso *dso)
-{
-	if (dso->loadmap) {
-		size_t i;
-		for (i=0; i<dso->loadmap->nsegs; i++) {
-			if (!dso->loadmap->segs[i].p_memsz)
-				continue;
-			munmap((void *)dso->loadmap->segs[i].addr,
-				dso->loadmap->segs[i].p_memsz);
-		}
-		free(dso->loadmap);
-	} else if (dso->map && dso->map_len) {
-		munmap(dso->map, dso->map_len);
-	}
-}
-
-static void *map_library(int fd, struct dso *dso)
-{
-	Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)];
-	void *allocated_buf=0;
-	size_t phsize;
-	size_t addr_min=SIZE_MAX, addr_max=0, map_len;
-	size_t this_min, this_max;
-	size_t nsegs = 0;
-	off_t off_start;
-	Ehdr *eh;
-	Phdr *ph, *ph0;
-	unsigned prot;
-	unsigned char *map=MAP_FAILED, *base;
-	size_t dyn=0;
-	size_t tls_image=0;
-	size_t i;
-
-	ssize_t l = read(fd, buf, sizeof buf);
-	eh = buf;
-	if (l<0) return 0;
-	if (l<sizeof *eh || (eh->e_type != ET_DYN && eh->e_type != ET_EXEC))
-		goto noexec;
-	phsize = eh->e_phentsize * eh->e_phnum;
-	if (phsize > sizeof buf - sizeof *eh) {
-		allocated_buf = malloc(phsize);
-		if (!allocated_buf) return 0;
-		l = pread(fd, allocated_buf, phsize, eh->e_phoff);
-		if (l < 0) goto error;
-		if (l != phsize) goto noexec;
-		ph = ph0 = allocated_buf;
-	} else if (eh->e_phoff + phsize > l) {
-		l = pread(fd, buf+1, phsize, eh->e_phoff);
-		if (l < 0) goto error;
-		if (l != phsize) goto noexec;
-		ph = ph0 = (void *)(buf + 1);
-	} else {
-		ph = ph0 = (void *)((char *)buf + eh->e_phoff);
-	}
-	for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
-		if (ph->p_type == PT_DYNAMIC) {
-			dyn = ph->p_vaddr;
-		} else if (ph->p_type == PT_TLS) {
-			tls_image = ph->p_vaddr;
-			dso->tls.align = ph->p_align;
-			dso->tls.len = ph->p_filesz;
-			dso->tls.size = ph->p_memsz;
-		} else if (ph->p_type == PT_GNU_RELRO) {
-			dso->relro_start = ph->p_vaddr & -PAGE_SIZE;
-			dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
-		} else if (ph->p_type == PT_GNU_STACK) {
-			if (!runtime && ph->p_memsz > __default_stacksize) {
-				__default_stacksize =
-					ph->p_memsz < DEFAULT_STACK_MAX ?
-					ph->p_memsz : DEFAULT_STACK_MAX;
-			}
-		}
-		if (ph->p_type != PT_LOAD) continue;
-		nsegs++;
-		if (ph->p_vaddr < addr_min) {
-			addr_min = ph->p_vaddr;
-			off_start = ph->p_offset;
-			prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
-				((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
-				((ph->p_flags&PF_X) ? PROT_EXEC : 0));
-		}
-		if (ph->p_vaddr+ph->p_memsz > addr_max) {
-			addr_max = ph->p_vaddr+ph->p_memsz;
-		}
-	}
-	if (!dyn) goto noexec;
-	if (DL_FDPIC && !(eh->e_flags & FDPIC_CONSTDISP_FLAG)) {
-		dso->loadmap = calloc(1, sizeof *dso->loadmap
-			+ nsegs * sizeof *dso->loadmap->segs);
-		if (!dso->loadmap) goto error;
-		dso->loadmap->nsegs = nsegs;
-		for (ph=ph0, i=0; i<nsegs; ph=(void *)((char *)ph+eh->e_phentsize)) {
-			if (ph->p_type != PT_LOAD) continue;
-			prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
-				((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
-				((ph->p_flags&PF_X) ? PROT_EXEC : 0));
-			map = mmap(0, ph->p_memsz + (ph->p_vaddr & PAGE_SIZE-1),
-				prot, MAP_PRIVATE,
-				fd, ph->p_offset & -PAGE_SIZE);
-			if (map == MAP_FAILED) {
-				unmap_library(dso);
-				goto error;
-			}
-			dso->loadmap->segs[i].addr = (size_t)map +
-				(ph->p_vaddr & PAGE_SIZE-1);
-			dso->loadmap->segs[i].p_vaddr = ph->p_vaddr;
-			dso->loadmap->segs[i].p_memsz = ph->p_memsz;
-			i++;
-			if (prot & PROT_WRITE) {
-				size_t brk = (ph->p_vaddr & PAGE_SIZE-1)
-					+ ph->p_filesz;
-				size_t pgbrk = brk + PAGE_SIZE-1 & -PAGE_SIZE;
-				size_t pgend = brk + ph->p_memsz - ph->p_filesz
-					+ PAGE_SIZE-1 & -PAGE_SIZE;
-				if (pgend > pgbrk && mmap_fixed(map+pgbrk,
-					pgend-pgbrk, prot,
-					MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,
-					-1, off_start) == MAP_FAILED)
-					goto error;
-				memset(map + brk, 0, pgbrk-brk);
-			}
-		}
-		map = (void *)dso->loadmap->segs[0].addr;
-		map_len = 0;
-		goto done_mapping;
-	}
-	addr_max += PAGE_SIZE-1;
-	addr_max &= -PAGE_SIZE;
-	addr_min &= -PAGE_SIZE;
-	off_start &= -PAGE_SIZE;
-	map_len = addr_max - addr_min + off_start;
-	/* The first time, we map too much, possibly even more than
-	 * the length of the file. This is okay because we will not
-	 * use the invalid part; we just need to reserve the right
-	 * amount of virtual address space to map over later. */
-	map = DL_NOMMU_SUPPORT
-		? mmap((void *)addr_min, map_len, PROT_READ|PROT_WRITE|PROT_EXEC,
-			MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
-		: mmap((void *)addr_min, map_len, prot,
-			MAP_PRIVATE, fd, off_start);
-	if (map==MAP_FAILED) goto error;
-	dso->map = map;
-	dso->map_len = map_len;
-	/* If the loaded file is not relocatable and the requested address is
-	 * not available, then the load operation must fail. */
-	if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) {
-		errno = EBUSY;
-		goto error;
-	}
-	base = map - addr_min;
-	dso->phdr = 0;
-	dso->phnum = 0;
-	for (ph=ph0, i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
-		if (ph->p_type != PT_LOAD) continue;
-		/* Check if the programs headers are in this load segment, and
-		 * if so, record the address for use by dl_iterate_phdr. */
-		if (!dso->phdr && eh->e_phoff >= ph->p_offset
-		    && eh->e_phoff+phsize <= ph->p_offset+ph->p_filesz) {
-			dso->phdr = (void *)(base + ph->p_vaddr
-				+ (eh->e_phoff-ph->p_offset));
-			dso->phnum = eh->e_phnum;
-			dso->phentsize = eh->e_phentsize;
-		}
-		this_min = ph->p_vaddr & -PAGE_SIZE;
-		this_max = ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE;
-		off_start = ph->p_offset & -PAGE_SIZE;
-		prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
-			((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
-			((ph->p_flags&PF_X) ? PROT_EXEC : 0));
-		/* Reuse the existing mapping for the lowest-address LOAD */
-		if ((ph->p_vaddr & -PAGE_SIZE) != addr_min || DL_NOMMU_SUPPORT)
-			if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
-				goto error;
-		if (ph->p_memsz > ph->p_filesz && (ph->p_flags&PF_W)) {
-			size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
-			size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
-			memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
-			if (pgbrk-(size_t)base < this_max && mmap_fixed((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
-				goto error;
-		}
-	}
-	for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
-		if (((size_t *)(base+dyn))[i]==DT_TEXTREL) {
-			if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC)
-			    && errno != ENOSYS)
-				goto error;
-			break;
-		}
-done_mapping:
-	dso->base = base;
-	dso->dynv = laddr(dso, dyn);
-	if (dso->tls.size) dso->tls.image = laddr(dso, tls_image);
-	free(allocated_buf);
-	return map;
-noexec:
-	errno = ENOEXEC;
-error:
-	if (map!=MAP_FAILED) unmap_library(dso);
-	free(allocated_buf);
-	return 0;
-}
-
 static int path_open(const char *name, const char *s, char *buf, size_t buf_size)
 {
 	size_t l;
diff --git a/ldso/map_library.h b/ldso/map_library.h
new file mode 100644
index 0000000..d685471
--- /dev/null
+++ b/ldso/map_library.h
@@ -0,0 +1,276 @@
+#include <errno.h>
+#include <features.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include "dynlink.h"
+#include "pthread_impl.h"
+
+/* Compute load address for a virtual address in a given dso. */
+#if DL_FDPIC
+static inline void *laddr(const struct dso *p, size_t v)
+{
+	size_t j=0;
+	if (!p->loadmap) return p->base + v;
+	for (j=0; v-p->loadmap->segs[j].p_vaddr >= p->loadmap->segs[j].p_memsz; j++);
+	return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
+}
+static inline void *laddr_pg(const struct dso *p, size_t v)
+{
+	size_t j=0;
+	size_t pgsz = PAGE_SIZE;
+	if (!p->loadmap) return p->base + v;
+	for (j=0; ; j++) {
+		size_t a = p->loadmap->segs[j].p_vaddr;
+		size_t b = a + p->loadmap->segs[j].p_memsz;
+		a &= -pgsz;
+		b += pgsz-1;
+		b &= -pgsz;
+		if (v-a<b-a) break;
+	}
+	return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
+}
+static void (*fdbarrier(void *p))()
+{
+	void (*fd)();
+	__asm__("" : "=r"(fd) : "0"(p));
+	return fd;
+}
+#define fpaddr(p, v) fdbarrier((&(struct funcdesc){ \
+	laddr(p, v), (p)->got }))
+#else
+#define laddr(p, v) (void *)((p)->base + (v))
+#define laddr_pg(p, v) laddr(p, v)
+#define fpaddr(p, v) ((void (*)())laddr(p, v))
+#endif
+
+static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off)
+{
+	static int no_map_fixed;
+	char *q;
+	if (!no_map_fixed) {
+		q = mmap(p, n, prot, flags|MAP_FIXED, fd, off);
+		if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL)
+			return q;
+		no_map_fixed = 1;
+	}
+	/* Fallbacks for MAP_FIXED failure on NOMMU kernels. */
+	if (flags & MAP_ANONYMOUS) {
+		memset(p, 0, n);
+		return p;
+	}
+	ssize_t r;
+	if (lseek(fd, off, SEEK_SET) < 0) return MAP_FAILED;
+	for (q=p; n; q+=r, off+=r, n-=r) {
+		r = read(fd, q, n);
+		if (r < 0 && errno != EINTR) return MAP_FAILED;
+		if (!r) {
+			memset(q, 0, n);
+			break;
+		}
+	}
+	return p;
+}
+
+static inline void unmap_library(struct dso *dso)
+{
+	if (dso->loadmap) {
+		size_t i;
+		for (i=0; i<dso->loadmap->nsegs; i++) {
+			if (!dso->loadmap->segs[i].p_memsz)
+				continue;
+			munmap((void *)dso->loadmap->segs[i].addr,
+				dso->loadmap->segs[i].p_memsz);
+		}
+		free(dso->loadmap);
+	} else if (dso->map && dso->map_len) {
+		munmap(dso->map, dso->map_len);
+	}
+}
+
+static inline void *map_library(int fd, struct dso *dso)
+{
+	Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)];
+	void *allocated_buf=0;
+	size_t phsize;
+	size_t ph_allocated_size;
+	size_t addr_min=SIZE_MAX, addr_max=0, map_len;
+	size_t this_min, this_max;
+	size_t nsegs = 0;
+	off_t off_start;
+	Ehdr *eh;
+	Phdr *ph, *ph0;
+	unsigned prot;
+	unsigned char *map=MAP_FAILED, *base;
+	size_t dyn=0;
+	size_t i;
+	size_t tls_image=0;
+
+	ssize_t l = read(fd, buf, sizeof buf);
+	eh = buf;
+	if (l<0) return 0;
+	if (l<sizeof *eh || (eh->e_type != ET_DYN && eh->e_type != ET_EXEC))
+		goto noexec;
+	phsize = eh->e_phentsize * eh->e_phnum;
+	if (phsize > sizeof buf - sizeof *eh) {
+		allocated_buf = malloc(phsize);
+		if (!allocated_buf) return 0;
+		l = pread(fd, allocated_buf, phsize, eh->e_phoff);
+		if (l < 0) goto error;
+		if (l != phsize) goto noexec;
+		ph = ph0 = allocated_buf;
+	} else if (eh->e_phoff + phsize > l) {
+		l = pread(fd, buf+1, phsize, eh->e_phoff);
+		if (l < 0) goto error;
+		if (l != phsize) goto noexec;
+		ph = ph0 = (void *)(buf + 1);
+	} else {
+		ph = ph0 = (void *)((char *)buf + eh->e_phoff);
+	}
+	for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
+		if (ph->p_type == PT_DYNAMIC) {
+			dyn = ph->p_vaddr;
+		} else if (ph->p_type == PT_TLS) {
+			tls_image = ph->p_vaddr;
+			dso->tls.align = ph->p_align;
+			dso->tls.len = ph->p_filesz;
+			dso->tls.size = ph->p_memsz;
+		} else if (ph->p_type == PT_GNU_RELRO) {
+			dso->relro_start = ph->p_vaddr & -PAGE_SIZE;
+			dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
+		} else if (ph->p_type == PT_GNU_STACK) {
+			if (!runtime && ph->p_memsz > __default_stacksize) {
+				__default_stacksize =
+					ph->p_memsz < DEFAULT_STACK_MAX ?
+					ph->p_memsz : DEFAULT_STACK_MAX;
+			}
+		}
+		if (ph->p_type != PT_LOAD) continue;
+		nsegs++;
+		if (ph->p_vaddr < addr_min) {
+			addr_min = ph->p_vaddr;
+			off_start = ph->p_offset;
+			prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
+				((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
+				((ph->p_flags&PF_X) ? PROT_EXEC : 0));
+		}
+		if (ph->p_vaddr+ph->p_memsz > addr_max) {
+			addr_max = ph->p_vaddr+ph->p_memsz;
+		}
+	}
+	if (!dyn) goto noexec;
+	if (DL_FDPIC && !(eh->e_flags & FDPIC_CONSTDISP_FLAG)) {
+		dso->loadmap = calloc(1, sizeof *dso->loadmap
+			+ nsegs * sizeof *dso->loadmap->segs);
+		if (!dso->loadmap) goto error;
+		dso->loadmap->nsegs = nsegs;
+		for (ph=ph0, i=0; i<nsegs; ph=(void *)((char *)ph+eh->e_phentsize)) {
+			if (ph->p_type != PT_LOAD) continue;
+			prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
+				((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
+				((ph->p_flags&PF_X) ? PROT_EXEC : 0));
+			map = mmap(0, ph->p_memsz + (ph->p_vaddr & PAGE_SIZE-1),
+				prot, MAP_PRIVATE,
+				fd, ph->p_offset & -PAGE_SIZE);
+			if (map == MAP_FAILED) {
+				unmap_library(dso);
+				goto error;
+			}
+			dso->loadmap->segs[i].addr = (size_t)map +
+				(ph->p_vaddr & PAGE_SIZE-1);
+			dso->loadmap->segs[i].p_vaddr = ph->p_vaddr;
+			dso->loadmap->segs[i].p_memsz = ph->p_memsz;
+			i++;
+			if (prot & PROT_WRITE) {
+				size_t brk = (ph->p_vaddr & PAGE_SIZE-1)
+					+ ph->p_filesz;
+				size_t pgbrk = brk + PAGE_SIZE-1 & -PAGE_SIZE;
+				size_t pgend = brk + ph->p_memsz - ph->p_filesz
+					+ PAGE_SIZE-1 & -PAGE_SIZE;
+				if (pgend > pgbrk && mmap_fixed(map+pgbrk,
+					pgend-pgbrk, prot,
+					MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,
+					-1, off_start) == MAP_FAILED)
+					goto error;
+				memset(map + brk, 0, pgbrk-brk);
+			}
+		}
+		map = (void *)dso->loadmap->segs[0].addr;
+		map_len = 0;
+		goto done_mapping;
+	}
+	addr_max += PAGE_SIZE-1;
+	addr_max &= -PAGE_SIZE;
+	addr_min &= -PAGE_SIZE;
+	off_start &= -PAGE_SIZE;
+	map_len = addr_max - addr_min + off_start;
+	/* The first time, we map too much, possibly even more than
+	 * the length of the file. This is okay because we will not
+	 * use the invalid part; we just need to reserve the right
+	 * amount of virtual address space to map over later. */
+	map = DL_NOMMU_SUPPORT
+		? mmap((void *)addr_min, map_len, PROT_READ|PROT_WRITE|PROT_EXEC,
+			MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+		: mmap((void *)addr_min, map_len, prot,
+			MAP_PRIVATE, fd, off_start);
+	if (map==MAP_FAILED) goto error;
+	dso->map = map;
+	dso->map_len = map_len;
+	/* If the loaded file is not relocatable and the requested address is
+	 * not available, then the load operation must fail. */
+	if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) {
+		errno = EBUSY;
+		goto error;
+	}
+	base = map - addr_min;
+	dso->phdr = 0;
+	dso->phnum = 0;
+	for (ph=ph0, i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
+		if (ph->p_type != PT_LOAD) continue;
+		/* Check if the programs headers are in this load segment, and
+		 * if so, record the address for use by dl_iterate_phdr. */
+		if (!dso->phdr && eh->e_phoff >= ph->p_offset
+		    && eh->e_phoff+phsize <= ph->p_offset+ph->p_filesz) {
+			dso->phdr = (void *)(base + ph->p_vaddr
+				+ (eh->e_phoff-ph->p_offset));
+			dso->phnum = eh->e_phnum;
+			dso->phentsize = eh->e_phentsize;
+		}
+		this_min = ph->p_vaddr & -PAGE_SIZE;
+		this_max = ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE;
+		off_start = ph->p_offset & -PAGE_SIZE;
+		prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
+			((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
+			((ph->p_flags&PF_X) ? PROT_EXEC : 0));
+		/* Reuse the existing mapping for the lowest-address LOAD */
+		if ((ph->p_vaddr & -PAGE_SIZE) != addr_min || DL_NOMMU_SUPPORT)
+			if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
+				goto error;
+		if (ph->p_memsz > ph->p_filesz && (ph->p_flags&PF_W)) {
+			size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
+			size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
+			memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
+			if (pgbrk-(size_t)base < this_max && mmap_fixed((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
+				goto error;
+		}
+	}
+	for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
+		if (((size_t *)(base+dyn))[i]==DT_TEXTREL) {
+			if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC)
+			    && errno != ENOSYS)
+				goto error;
+			break;
+		}
+done_mapping:
+	dso->base = base;
+	dso->dynv = laddr(dso, dyn);
+	if (dso->tls.size) dso->tls.image = laddr(dso, tls_image);
+	free(allocated_buf);
+	return map;
+noexec:
+	errno = ENOEXEC;
+error:
+	if (map!=MAP_FAILED) unmap_library(dso);
+	free(allocated_buf);
+	return 0;
+}
-- 
2.7.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [musl] [PATCH 4/4] crt: add dcrt1, with support for locating the dynamic loader at runtime
  2020-03-29  0:19 [musl] [PATCH 1/4] ldso: add option to rewrite the argv block rcombs
  2020-03-29  0:19 ` [musl] [PATCH 2/4] ldso: when run via CLI, set auxv as if the app was loaded by the kernel rcombs
  2020-03-29  0:19 ` [musl] [PATCH 3/4] ldso: move (un)map_library functions to separate file rcombs
@ 2020-03-29  0:19 ` rcombs
  2020-03-29  2:54 ` [musl] [PATCH 1/4] ldso: add option to rewrite the argv block Rich Felker
  3 siblings, 0 replies; 6+ messages in thread
From: rcombs @ 2020-03-29  0:19 UTC (permalink / raw)
  To: musl

---
 Makefile                |  10 +-
 crt/dcrt1.c             | 372 ++++++++++++++++++++++++++++++++++++++++++++++++
 ldso/dlstart.c          |  59 +++++---
 ldso/dynlink.c          |  13 ++
 ldso/map_library.h      |  59 ++++----
 tools/ld.musl-clang.in  |  17 ++-
 tools/musl-clang.in     |   8 ++
 tools/musl-gcc.specs.sh |   4 +-
 8 files changed, 490 insertions(+), 52 deletions(-)
 create mode 100644 crt/dcrt1.c

diff --git a/Makefile b/Makefile
index bd8f5c3..348ffd0 100644
--- a/Makefile
+++ b/Makefile
@@ -106,13 +106,15 @@ obj/src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
 
 obj/src/internal/version.o obj/src/internal/version.lo: obj/src/internal/version.h
 
-obj/crt/rcrt1.o obj/ldso/dlstart.lo obj/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
+obj/crt/rcrt1.o obj/crt/dcrt1.o obj/ldso/dlstart.lo obj/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
 
-obj/crt/crt1.o obj/crt/scrt1.o obj/crt/rcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
+obj/crt/crt1.o obj/crt/scrt1.o obj/crt/rcrt1.o obj/crt/dcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
 
-obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart.c
+obj/crt/rcrt1.o obj/crt/dcrt1.o: $(srcdir)/ldso/dlstart.c
 
-obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC
+obj/crt/Scrt1.o obj/crt/rcrt1.o obj/crt/dcrt1.o: CFLAGS_ALL += -fPIC
+
+obj/crt/dcrt1.o: CFLAGS_ALL += -DLDSO_PATHNAME=\"$(LDSO_PATHNAME)\"
 
 OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%))
 $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3
diff --git a/crt/dcrt1.c b/crt/dcrt1.c
new file mode 100644
index 0000000..d58a606
--- /dev/null
+++ b/crt/dcrt1.c
@@ -0,0 +1,372 @@
+#define SYSCALL_NO_TLS 1
+
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <features.h>
+#include <libgen.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <unistd.h>
+#include "atomic.h"
+#include "dynlink.h"
+#include "syscall.h"
+
+extern weak hidden const size_t _DYNAMIC[];
+
+int main();
+weak void _init();
+weak void _fini();
+weak _Noreturn int __libc_start_main(int (*)(), int, char **,
+	void (*)(), void(*)(), void(*)());
+
+#define START "_start"
+#define _dlstart_c _start_c
+#define DL_DNI
+#include "../ldso/dlstart.c"
+
+struct dso {
+	unsigned char *base;
+	struct fdpic_loadmap *loadmap;
+	size_t *dynv;
+	Phdr *phdr;
+	int phnum;
+	size_t phentsize;
+	unsigned char *map;
+	size_t map_len;
+};
+
+#ifndef PAGESIZE
+#ifdef PAGE_SIZE
+#undef PAGE_SIZE // We don't want to use libc.page_size here
+#endif
+static size_t page_size;
+#define PAGE_SIZE page_size
+#endif
+
+#ifdef SYS_mmap2
+#define mmap(start, len, prot, flags, fd, off) (void*)__syscall(SYS_mmap2, start, len, prot, flags, fd, off/SYSCALL_MMAP2_UNIT)
+#else
+#define mmap(start, len, prot, flags, fd, off) (void*)__syscall(SYS_mmap, start, len, prot, flags, fd, off)
+#endif
+
+#define munmap(ptr, len) __syscall(SYS_munmap, ptr, len)
+
+static inline int crt_mprotect(void *addr, size_t len, int prot)
+{
+	size_t start, end;
+	start = (size_t)addr & -PAGE_SIZE;
+	end = (size_t)((char *)addr + len + PAGE_SIZE-1) & -PAGE_SIZE;
+	return __syscall(SYS_mprotect, start, end-start, prot);
+}
+#define mprotect crt_mprotect
+
+#define read(fd, buf, size) __syscall(SYS_read, fd, buf, size)
+#define pread(fd, buf, size, ofs) __syscall(SYS_pread, fd, buf, size, __SYSCALL_LL_PRW(ofs))
+
+static inline off_t crt_lseek(int fd, off_t offset, int whence)
+{
+#ifdef SYS__llseek
+	off_t result;
+	return __syscall(SYS__llseek, fd, offset>>32, offset, &result, whence) ? -1 : result;
+#else
+	return __syscall(SYS_lseek, fd, offset, whence);
+#endif
+}
+#define lseek crt_lseek
+
+static inline void *map_library_allocz(size_t *size)
+{
+	void *ret;
+	*size = (*size + SYSCALL_MMAP2_UNIT - 1) & -SYSCALL_MMAP2_UNIT;
+	ret = mmap(0, *size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (ret == MAP_FAILED)
+		return NULL;
+	return ret;
+}
+
+static inline void map_library_free(void *ptr, size_t size)
+{
+	if (ptr)
+		munmap(ptr, size);
+}
+
+#define map_library_failed(val) ((unsigned long)val > -4096UL)
+#define map_library_error(ret) (-(long)ret)
+
+#ifdef SYS_readlink
+#define readlink(path, buf, bufsize) __syscall(SYS_readlink, path, buf, bufsize)
+#else
+#define readlink(path, buf, bufsize) __syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsize)
+#endif
+
+#ifdef SYS_access
+#define access(filename, amode) __syscall(SYS_access, filename, amode)
+#else
+#define access(filename, amode) __syscall(SYS_faccessat, AT_FDCWD, filename, amode, 0)
+#endif
+
+static void *crt_memcpy(void *restrict dest, const void *restrict src, size_t n)
+{
+	unsigned char *d = dest;
+	const unsigned char *s = src;
+	for (; n; n--) *d++ = *s++;
+	return dest;
+}
+
+static void *crt_memset(void *dest, int c, size_t n)
+{
+	unsigned char *s = dest;
+	for (; n; n--, s++) *s = c;
+	return dest;
+}
+#define memset crt_memset
+
+static size_t crt_strlen(const char *s)
+{
+	const char *a = s;
+	for (; *s; s++);
+	return s-a;
+}
+
+static char *crt_strchrnul(const char *s, int c)
+{
+	c = (unsigned char)c;
+	if (!c) return (char *)s + crt_strlen(s);
+	for (; *s && *(unsigned char *)s != c; s++);
+	return (char *)s;
+}
+
+static int crt_strncmp(const char *_l, const char *_r, size_t n)
+{
+	const unsigned char *l=(void *)_l, *r=(void *)_r;
+	if (!n--) return 0;
+	for (; *l && *r && n && *l == *r ; l++, r++, n--);
+	return *l - *r;
+}
+
+static char *crt_getenv(const char *name, char **environ)
+{
+	size_t l = crt_strchrnul(name, '=') - name;
+	if (l && !name[l] && environ)
+		for (char **e = environ; *e; e++)
+			if (!crt_strncmp(name, *e, l) && l[*e] == '=')
+				return *e + l+1;
+	return 0;
+}
+
+#define LD_CRT
+#include "../ldso/map_library.h"
+
+static void decode_vec(const size_t *v, size_t *a, size_t cnt)
+{
+	size_t i;
+	for (i=0; i<cnt; i++) a[i] = 0;
+	for (; v[0]; v+=2) if (v[0]-1<cnt-1) {
+		a[0] |= 1UL<<v[0];
+		a[v[0]] = v[1];
+	}
+}
+
+static void get_rpath(const char **runpath, const size_t *dyn, unsigned char *base)
+{
+	/* DT_STRTAB is pre-relocated for us by dlstart */
+	const char *strings = (char*)base + dyn[DT_STRTAB];
+
+	*runpath = NULL;
+
+	if (dyn[0] & (1 << DT_RPATH))
+		*runpath = strings + dyn[DT_RPATH];
+	if (dyn[0] & (1 << DT_RUNPATH))
+		*runpath = strings + dyn[DT_RUNPATH];
+}
+
+static size_t find_linker(char *outbuf, size_t bufsize, const char *this_path, size_t thisl, const size_t *dyn, unsigned char *base, char **environ, int secure)
+{
+	const char *paths[2]; // envpath, rpath/runpath
+	size_t i;
+	int fd;
+
+	// In the suid/secure case, skip everything and use the fixed path
+	if (secure)
+		goto default_path;
+
+	// Strip filename
+	if (thisl)
+		thisl--;
+	while (thisl > 1 && this_path[thisl] == '/')
+		thisl--;
+	while (thisl > 0 && this_path[thisl] != '/')
+		thisl--;
+
+	const char *envpath = crt_getenv("LD_LOADER_PATH", environ);
+	if (envpath) {
+		size_t envlen = crt_strlen(envpath);
+		if (envlen < bufsize) {
+			crt_memcpy(outbuf, envpath, envlen + 1);
+			return envlen + 1;
+		}
+	}
+
+	get_rpath(&paths[1], dyn, base);
+
+	paths[0] = crt_getenv("LD_LIBRARY_PATH", environ);
+
+	for (i = 0; i < 2; i++) {
+		const char *p = paths[i];
+		char *o = outbuf;
+		if (!p)
+			continue;
+		for (;;) {
+			if (!crt_strncmp(p, "$ORIGIN", 7) ||
+					!crt_strncmp(p, "${ORIGIN}", 9)) {
+				if (o + thisl + 1 < outbuf + bufsize) {
+					crt_memcpy(o, this_path, thisl);
+					o += thisl;
+				} else {
+					o = outbuf + bufsize - 1;
+				}
+				p += (p[1] == '{' ? 9 : 7);
+			} else if (*p == ':' || !*p) {
+#define LDSO_FILENAME "ld-musl-" LDSO_ARCH ".so.1"
+				if (o + sizeof(LDSO_FILENAME) + 1 < outbuf + bufsize) {
+					*o++ = '/';
+					crt_memcpy(o, LDSO_FILENAME, sizeof(LDSO_FILENAME));
+					if (!access(outbuf, R_OK | X_OK))
+						return (o + sizeof(LDSO_FILENAME)) - outbuf;
+				}
+				if (!*p)
+					break;
+				o = outbuf;
+				p++;
+			} else {
+				if (o < outbuf + bufsize)
+					*o++ = *p;
+				p++;
+			}
+		}
+	}
+
+	default_path:
+	// Didn't find a usable loader anywhere (or in secure mode), so try the default
+	crt_memcpy(outbuf, LDSO_PATHNAME, sizeof(LDSO_PATHNAME));
+	return sizeof(LDSO_PATHNAME);
+}
+
+hidden _Noreturn void __dls2(unsigned char *base, size_t *p)
+{
+	int argc = p[0];
+	char **argv = (void *)(p+1);
+	int fd;
+	int secure;
+	int prot = PROT_READ;
+	struct dso loader;
+	Ehdr *loader_hdr;
+	Phdr *new_hdr;
+	void *entry;
+	char this_path[PATH_MAX];
+	size_t thisl;
+	char linker_path[PATH_MAX];
+	size_t linker_len;
+	size_t i;
+	size_t aux[AUX_CNT];
+	size_t *auxv;
+	size_t dyn[DYN_CNT];
+	char **environ = argv + argc + 1;
+
+	// We're already finished here; just run main.
+	if (__libc_start_main)
+		__libc_start_main(main, argc, argv, _init, _fini, 0);
+
+	/* Find aux vector just past environ[] and use it to initialize
+	* global data that may be needed before we can make syscalls. */
+	for (i = argc + 1; argv[i]; i++);
+	auxv = (void *)(argv + i + 1);
+	decode_vec(auxv, aux, AUX_CNT);
+	secure = ((aux[0] & 0x7800) != 0x7800 || aux[AT_UID] != aux[AT_EUID]
+		|| aux[AT_GID] != aux[AT_EGID] || aux[AT_SECURE]);
+
+#ifndef PAGESIZE
+	page_size = aux[AT_PAGESZ];
+#endif
+
+	decode_vec(_DYNAMIC, dyn, DYN_CNT);
+
+	thisl = readlink("/proc/self/exe", this_path, sizeof this_path);
+	linker_len = find_linker(linker_path, sizeof linker_path, this_path, thisl, dyn, base, environ, secure);
+
+	fd = __sys_open2(, linker_path, O_RDONLY);
+	if (fd < 0)
+		goto error;
+
+	loader_hdr = map_library(fd, &loader);
+	if (!loader_hdr)
+		goto error;
+
+	__syscall(SYS_close, fd);
+
+	// Copy the program headers into an anonymous mapping
+	new_hdr = mmap(0, (aux[AT_PHENT] * (aux[AT_PHNUM] + 2) + linker_len + PAGE_SIZE - 1) & -PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (map_library_failed(new_hdr))
+		goto error;
+
+	// Point it back at the original kernel-provided base
+	new_hdr->p_type = PT_PHDR;
+	new_hdr->p_vaddr = (size_t)new_hdr - (size_t)base;
+
+	((Phdr*)((char*)new_hdr + aux[AT_PHENT]))->p_type = PT_INTERP;
+	((Phdr*)((char*)new_hdr + aux[AT_PHENT]))->p_vaddr = new_hdr->p_vaddr + aux[AT_PHENT] * (aux[AT_PHNUM] + 2);
+
+	crt_memcpy((char*)new_hdr + aux[AT_PHENT] * (aux[AT_PHNUM] + 2), linker_path, linker_len);
+
+	for (i = 0; i < aux[AT_PHNUM]; i++) {
+		Phdr *hdr = (void*)((char*)aux[AT_PHDR] + aux[AT_PHENT] * i);
+		Phdr *dst = (void*)((char*)new_hdr + aux[AT_PHENT] * (i + 2));
+		if (hdr->p_type == PT_PHDR || hdr->p_type == PT_INTERP) {
+			// Can't have a duplicate
+			dst->p_type = PT_NULL;
+		} else {
+			crt_memcpy(dst, hdr, aux[AT_PHENT]);
+		}
+	}
+
+	if (mprotect(new_hdr, aux[AT_PHENT] * (aux[AT_PHNUM] + 2) + linker_len, PROT_READ))
+		goto error;
+
+	for (i=0; auxv[i]; i+=2) {
+		if (auxv[i] == AT_BASE)
+			auxv[i + 1] = (size_t)loader_hdr;
+		if (auxv[i] == AT_PHDR)
+			auxv[i + 1] = (size_t)new_hdr;
+		if (auxv[i] == AT_PHNUM)
+			auxv[i + 1] += 2;
+	}
+
+	entry = laddr(&loader, loader_hdr->e_entry);
+
+#ifndef LD_FDPIC
+	/* Undo the relocations performed by dlstart */
+
+	if (NEED_MIPS_GOT_RELOCS) {
+		const size_t *dynv = _DYNAMIC;
+		size_t local_cnt = 0;
+		size_t *got = (void *)(base + dyn[DT_PLTGOT]);
+		for (i=0; dynv[i]; i+=2) if (dynv[i]==DT_MIPS_LOCAL_GOTNO)
+			local_cnt = dynv[i+1];
+		for (i=0; i<local_cnt; i++) got[i] -= (size_t)base;
+	}
+
+	size_t *rel = (void *)((size_t)base+dyn[DT_REL]);
+	size_t rel_size = dyn[DT_RELSZ];
+	for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t)) {
+		if (!IS_RELATIVE(rel[1], 0)) continue;
+		size_t *rel_addr = (void *)((size_t)base + rel[0]);
+		*rel_addr -= (size_t)base;
+	}
+#endif
+
+	CRTJMP(entry, argv - 1);
+
+error:
+	for(;;) a_crash();
+}
diff --git a/ldso/dlstart.c b/ldso/dlstart.c
index 20d50f2..49e6a99 100644
--- a/ldso/dlstart.c
+++ b/ldso/dlstart.c
@@ -21,7 +21,7 @@
 hidden void _dlstart_c(size_t *sp, size_t *dynv)
 {
 	size_t i, aux[AUX_CNT], dyn[DYN_CNT];
-	size_t *rel, rel_size, base;
+	size_t *rel, rel_size, base, loader_phdr;
 
 	int argc = *sp;
 	char **argv = (void *)(sp+1);
@@ -41,6 +41,13 @@ hidden void _dlstart_c(size_t *sp, size_t *dynv)
 		 * space and moving the extra fdpic arguments to the stack
 		 * vector where they are easily accessible from C. */
 		segs = ((struct fdpic_loadmap *)(sp[-1] ? sp[-1] : sp[-2]))->segs;
+		if (aux[AT_BASE]) {
+			Ehdr *eh = (void*)aux[AT_BASE];
+			for (i = 0; eh->e_phoff - segs[i].p_vaddr >= segs[i].p_memsz; i++);
+			loader_phdr = (eh->e_phoff - segs[i].p_vaddr + segs[i].addr);
+		} else {
+			loader_phdr = aux[AT_PHDR];
+		}
 	} else {
 		/* If dynv is null, the entry point was started from loader
 		 * that is not fdpic-aware. We can assume normal fixed-
@@ -55,6 +62,7 @@ hidden void _dlstart_c(size_t *sp, size_t *dynv)
 		segs[0].p_memsz = -1;
 		Ehdr *eh = (void *)base;
 		Phdr *ph = (void *)(base + eh->e_phoff);
+		loader_phdr = (size_t)ph;
 		size_t phnum = eh->e_phnum;
 		size_t phent = eh->e_phentsize;
 		while (phnum-- && ph->p_type != PT_DYNAMIC)
@@ -69,13 +77,42 @@ hidden void _dlstart_c(size_t *sp, size_t *dynv)
 
 #if DL_FDPIC
 	for (i=0; i<DYN_CNT; i++) {
-		if (i==DT_RELASZ || i==DT_RELSZ) continue;
+		if (i==DT_RELASZ || i==DT_RELSZ || i==DT_RPATH || i==DT_RUNPATH) continue;
 		if (!dyn[i]) continue;
 		for (j=0; dyn[i]-segs[j].p_vaddr >= segs[j].p_memsz; j++);
 		dyn[i] += segs[j].addr - segs[j].p_vaddr;
 	}
 	base = 0;
+#else
+	/* If the dynamic linker is invoked as a command, its load
+	 * address is not available in the aux vector. Instead, compute
+	 * the load address as the difference between &_DYNAMIC and the
+	 * virtual address in the PT_DYNAMIC program header. */
+	base = aux[AT_BASE];
+	if (!base) {
+		size_t phnum = aux[AT_PHNUM];
+		size_t phentsize = aux[AT_PHENT];
+		Phdr *ph = (void *)aux[AT_PHDR];
+		for (i=phnum; i--; ph = (void *)((char *)ph + phentsize)) {
+			if (ph->p_type == PT_DYNAMIC) {
+				base = (size_t)dynv - ph->p_vaddr;
+				break;
+			}
+		}
+	}
+	loader_phdr = base + ((Ehdr*)base)->e_phoff;
+#endif
 
+#ifdef DL_DNI
+	/* If AT_PHDR doesn't match the PHDR in AT_BASE, then we've been loaded as a
+	 * dynamic executable and ld.so has already been run, either by  the kernel,
+	 * or by dcrt. This means relocs are already finished (and doing them again
+	 * would break DT_RELs), so we can just skip to the stage-2 jump. */
+	if (aux[AT_PHDR] != loader_phdr)
+		goto skip_relocs;
+#endif
+
+#if DL_FDPIC
 	const Sym *syms = (void *)dyn[DT_SYMTAB];
 
 	rel = (void *)dyn[DT_RELA];
@@ -97,23 +134,6 @@ hidden void _dlstart_c(size_t *sp, size_t *dynv)
 		}
 	}
 #else
-	/* If the dynamic linker is invoked as a command, its load
-	 * address is not available in the aux vector. Instead, compute
-	 * the load address as the difference between &_DYNAMIC and the
-	 * virtual address in the PT_DYNAMIC program header. */
-	base = aux[AT_BASE];
-	if (!base) {
-		size_t phnum = aux[AT_PHNUM];
-		size_t phentsize = aux[AT_PHENT];
-		Phdr *ph = (void *)aux[AT_PHDR];
-		for (i=phnum; i--; ph = (void *)((char *)ph + phentsize)) {
-			if (ph->p_type == PT_DYNAMIC) {
-				base = (size_t)dynv - ph->p_vaddr;
-				break;
-			}
-		}
-	}
-
 	/* MIPS uses an ugly packed form for GOT relocations. Since we
 	 * can't make function calls yet and the code is tiny anyway,
 	 * it's simply inlined here. */
@@ -143,6 +163,7 @@ hidden void _dlstart_c(size_t *sp, size_t *dynv)
 #endif
 
 	stage2_func dls2;
+skip_relocs:
 	GETFUNCSYM(&dls2, __dls2, base+dyn[DT_PLTGOT]);
 	dls2((void *)base, sp);
 }
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 0e557b1..329a9e7 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -154,6 +154,19 @@ extern hidden void (*const __init_array_end)(void), (*const __fini_array_end)(vo
 weak_alias(__init_array_start, __init_array_end);
 weak_alias(__fini_array_start, __fini_array_end);
 
+static inline void *map_library_allocz(size_t *size)
+{
+	return calloc(1, *size);
+}
+
+static inline void map_library_free(void *ptr, size_t size)
+{
+	return free(ptr);
+}
+
+#define map_library_failed(ptr) (ptr == MAP_FAILED)
+#define map_library_error(val) (errno)
+
 #include "map_library.h"
 
 static int dl_strcmp(const char *l, const char *r)
diff --git a/ldso/map_library.h b/ldso/map_library.h
index d685471..2b3faee 100644
--- a/ldso/map_library.h
+++ b/ldso/map_library.h
@@ -1,11 +1,3 @@
-#include <errno.h>
-#include <features.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include "dynlink.h"
-#include "pthread_impl.h"
-
 /* Compute load address for a virtual address in a given dso. */
 #if DL_FDPIC
 static inline void *laddr(const struct dso *p, size_t v)
@@ -50,7 +42,7 @@ static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t of
 	char *q;
 	if (!no_map_fixed) {
 		q = mmap(p, n, prot, flags|MAP_FIXED, fd, off);
-		if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL)
+		if (!DL_NOMMU_SUPPORT || !map_library_failed(q) || map_library_error(q) != EINVAL)
 			return q;
 		no_map_fixed = 1;
 	}
@@ -63,7 +55,7 @@ static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t of
 	if (lseek(fd, off, SEEK_SET) < 0) return MAP_FAILED;
 	for (q=p; n; q+=r, off+=r, n-=r) {
 		r = read(fd, q, n);
-		if (r < 0 && errno != EINTR) return MAP_FAILED;
+		if (r < 0 && map_library_error(r) != EINTR) return MAP_FAILED;
 		if (!r) {
 			memset(q, 0, n);
 			break;
@@ -72,6 +64,11 @@ static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t of
 	return p;
 }
 
+static inline int map_library_error_check(int ret, int expected)
+{
+	return ret && map_library_error(ret) != expected;
+}
+
 static inline void unmap_library(struct dso *dso)
 {
 	if (dso->loadmap) {
@@ -82,7 +79,7 @@ static inline void unmap_library(struct dso *dso)
 			munmap((void *)dso->loadmap->segs[i].addr,
 				dso->loadmap->segs[i].p_memsz);
 		}
-		free(dso->loadmap);
+		map_library_free(dso->loadmap, dso->map_len);
 	} else if (dso->map && dso->map_len) {
 		munmap(dso->map, dso->map_len);
 	}
@@ -92,8 +89,8 @@ static inline void *map_library(int fd, struct dso *dso)
 {
 	Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)];
 	void *allocated_buf=0;
+	size_t allocated_buf_size;
 	size_t phsize;
-	size_t ph_allocated_size;
 	size_t addr_min=SIZE_MAX, addr_max=0, map_len;
 	size_t this_min, this_max;
 	size_t nsegs = 0;
@@ -104,7 +101,9 @@ static inline void *map_library(int fd, struct dso *dso)
 	unsigned char *map=MAP_FAILED, *base;
 	size_t dyn=0;
 	size_t i;
+#ifndef LD_CRT
 	size_t tls_image=0;
+#endif
 
 	ssize_t l = read(fd, buf, sizeof buf);
 	eh = buf;
@@ -113,7 +112,8 @@ static inline void *map_library(int fd, struct dso *dso)
 		goto noexec;
 	phsize = eh->e_phentsize * eh->e_phnum;
 	if (phsize > sizeof buf - sizeof *eh) {
-		allocated_buf = malloc(phsize);
+		allocated_buf_size = phsize;
+		allocated_buf = map_library_allocz(&allocated_buf_size);
 		if (!allocated_buf) return 0;
 		l = pread(fd, allocated_buf, phsize, eh->e_phoff);
 		if (l < 0) goto error;
@@ -130,6 +130,7 @@ static inline void *map_library(int fd, struct dso *dso)
 	for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
 		if (ph->p_type == PT_DYNAMIC) {
 			dyn = ph->p_vaddr;
+#ifndef LD_CRT
 		} else if (ph->p_type == PT_TLS) {
 			tls_image = ph->p_vaddr;
 			dso->tls.align = ph->p_align;
@@ -144,6 +145,7 @@ static inline void *map_library(int fd, struct dso *dso)
 					ph->p_memsz < DEFAULT_STACK_MAX ?
 					ph->p_memsz : DEFAULT_STACK_MAX;
 			}
+#endif
 		}
 		if (ph->p_type != PT_LOAD) continue;
 		nsegs++;
@@ -160,8 +162,8 @@ static inline void *map_library(int fd, struct dso *dso)
 	}
 	if (!dyn) goto noexec;
 	if (DL_FDPIC && !(eh->e_flags & FDPIC_CONSTDISP_FLAG)) {
-		dso->loadmap = calloc(1, sizeof *dso->loadmap
-			+ nsegs * sizeof *dso->loadmap->segs);
+		dso->map_len = sizeof *dso->loadmap + nsegs * sizeof *dso->loadmap->segs;
+		dso->loadmap = map_library_allocz(&dso->map_len);
 		if (!dso->loadmap) goto error;
 		dso->loadmap->nsegs = nsegs;
 		for (ph=ph0, i=0; i<nsegs; ph=(void *)((char *)ph+eh->e_phentsize)) {
@@ -172,7 +174,7 @@ static inline void *map_library(int fd, struct dso *dso)
 			map = mmap(0, ph->p_memsz + (ph->p_vaddr & PAGE_SIZE-1),
 				prot, MAP_PRIVATE,
 				fd, ph->p_offset & -PAGE_SIZE);
-			if (map == MAP_FAILED) {
+			if (map_library_failed(map)) {
 				unmap_library(dso);
 				goto error;
 			}
@@ -187,10 +189,10 @@ static inline void *map_library(int fd, struct dso *dso)
 				size_t pgbrk = brk + PAGE_SIZE-1 & -PAGE_SIZE;
 				size_t pgend = brk + ph->p_memsz - ph->p_filesz
 					+ PAGE_SIZE-1 & -PAGE_SIZE;
-				if (pgend > pgbrk && mmap_fixed(map+pgbrk,
+				if (pgend > pgbrk && !map_library_failed(mmap_fixed(map+pgbrk,
 					pgend-pgbrk, prot,
 					MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,
-					-1, off_start) == MAP_FAILED)
+					-1, off_start)))
 					goto error;
 				memset(map + brk, 0, pgbrk-brk);
 			}
@@ -213,13 +215,15 @@ static inline void *map_library(int fd, struct dso *dso)
 			MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
 		: mmap((void *)addr_min, map_len, prot,
 			MAP_PRIVATE, fd, off_start);
-	if (map==MAP_FAILED) goto error;
+	if (map_library_failed(map)) goto error;
 	dso->map = map;
 	dso->map_len = map_len;
 	/* If the loaded file is not relocatable and the requested address is
 	 * not available, then the load operation must fail. */
 	if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) {
+#ifndef LD_CRT
 		errno = EBUSY;
+#endif
 		goto error;
 	}
 	base = map - addr_min;
@@ -244,33 +248,36 @@ static inline void *map_library(int fd, struct dso *dso)
 			((ph->p_flags&PF_X) ? PROT_EXEC : 0));
 		/* Reuse the existing mapping for the lowest-address LOAD */
 		if ((ph->p_vaddr & -PAGE_SIZE) != addr_min || DL_NOMMU_SUPPORT)
-			if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
+			if (map_library_failed(mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start)))
 				goto error;
 		if (ph->p_memsz > ph->p_filesz && (ph->p_flags&PF_W)) {
 			size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
 			size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
 			memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
-			if (pgbrk-(size_t)base < this_max && mmap_fixed((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
+			if (pgbrk-(size_t)base < this_max && map_library_failed(mmap_fixed((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0)))
 				goto error;
 		}
 	}
 	for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
 		if (((size_t *)(base+dyn))[i]==DT_TEXTREL) {
-			if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC)
-			    && errno != ENOSYS)
+			if (map_library_error_check(mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC), ENOSYS))
 				goto error;
 			break;
 		}
 done_mapping:
 	dso->base = base;
 	dso->dynv = laddr(dso, dyn);
+#ifndef LD_CRT
 	if (dso->tls.size) dso->tls.image = laddr(dso, tls_image);
-	free(allocated_buf);
+#endif
+	map_library_free(allocated_buf, allocated_buf_size);
 	return map;
 noexec:
+#ifndef LD_CRT
 	errno = ENOEXEC;
+#endif
 error:
-	if (map!=MAP_FAILED) unmap_library(dso);
-	free(allocated_buf);
+	if (!map_library_failed(map)) unmap_library(dso);
+	map_library_free(allocated_buf, allocated_buf_size);
 	return 0;
 }
diff --git a/tools/ld.musl-clang.in b/tools/ld.musl-clang.in
index 93763d6..02d9893 100644
--- a/tools/ld.musl-clang.in
+++ b/tools/ld.musl-clang.in
@@ -7,6 +7,18 @@ shared=
 userlinkdir=
 userlink=
 
+Scrt="$libc_lib/Scrt1.o"
+dynamic_linker_args="-dynamic-linker \"$ldso\""
+
+for x ; do
+    case "$x" in
+        -l-dni)
+            dynamic_linker_args="-no-dynamic-linker"
+            Scrt="$libc_lib/dcrt1.o"
+            ;;
+    esac
+done
+
 for x ; do
     test "$cleared" || set -- ; cleared=1
 
@@ -42,10 +54,13 @@ for x ; do
             ;;
         -sysroot=*|--sysroot=*)
             ;;
+        $libc_lib/Scrt1.o)
+            set -- "$@" $Scrt
+            ;;
         *)
             set -- "$@" "$x"
             ;;
     esac
 done
 
-exec $($cc -print-prog-name=ld) -nostdlib "$@" -lc -dynamic-linker "$ldso"
+exec $($cc -print-prog-name=ld) -nostdlib "$@" -lc "$dynamic_linker_args"
diff --git a/tools/musl-clang.in b/tools/musl-clang.in
index 623de6f..49cba1b 100644
--- a/tools/musl-clang.in
+++ b/tools/musl-clang.in
@@ -5,14 +5,21 @@ libc_inc="@INCDIR@"
 libc_lib="@LIBDIR@"
 thisdir="`cd "$(dirname "$0")"; pwd`"
 
+cleared=
+
 # prevent clang from running the linker (and erroring) on no input.
 sflags=
 eflags=
+dniflags=
 for x ; do
+    test "$cleared" || set -- ; cleared=1
+
     case "$x" in
+        --dni) dniflags=-l-dni; continue ;;
         -l*) input=1 ;;
         *) input= ;;
     esac
+    set -- "$@" "$x"
     if test "$input" ; then
         sflags="-l-user-start"
         eflags="-l-user-end"
@@ -29,6 +36,7 @@ exec $cc \
     -isystem "$libc_inc" \
     -L-user-start \
     $sflags \
+    $dniflags \
     "$@" \
     $eflags \
     -L"$libc_lib" \
diff --git a/tools/musl-gcc.specs.sh b/tools/musl-gcc.specs.sh
index 3049257..86374f1 100644
--- a/tools/musl-gcc.specs.sh
+++ b/tools/musl-gcc.specs.sh
@@ -17,13 +17,13 @@ cat <<EOF
 libgcc.a%s %:if-exists(libgcc_eh.a%s)
 
 *startfile:
-%{!shared: $libdir/Scrt1.o} $libdir/crti.o crtbeginS.o%s
+%{!shared: %{-dni:$libdir/dcrt1.o;:$libdir/Scrt1.o}} $libdir/crti.o crtbeginS.o%s
 
 *endfile:
 crtendS.o%s $libdir/crtn.o
 
 *link:
--dynamic-linker $ldso -nostdlib %{shared:-shared} %{static:-static} %{rdynamic:-export-dynamic}
+%{-dni:-no-dynamic-linker;:--dynamic-linker $ldso} -nostdlib %{shared:-shared} %{static:-static} %{rdynamic:-export-dynamic}
 
 *esp_link:
 
-- 
2.7.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [musl] [PATCH 1/4] ldso: add option to rewrite the argv block
  2020-03-29  0:19 [musl] [PATCH 1/4] ldso: add option to rewrite the argv block rcombs
                   ` (2 preceding siblings ...)
  2020-03-29  0:19 ` [musl] [PATCH 4/4] crt: add dcrt1, with support for locating the dynamic loader at runtime rcombs
@ 2020-03-29  2:54 ` Rich Felker
  3 siblings, 0 replies; 6+ messages in thread
From: Rich Felker @ 2020-03-29  2:54 UTC (permalink / raw)
  To: musl

On Sat, Mar 28, 2020 at 07:19:25PM -0500, rcombs wrote:
> ---
>  ldso/dynlink.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/ldso/dynlink.c b/ldso/dynlink.c
> index 6468f20..c378f00 100644
> --- a/ldso/dynlink.c
> +++ b/ldso/dynlink.c
> @@ -1698,6 +1698,7 @@ void __dls3(size_t *sp, size_t *auxv)
>  	char **argv = (void *)(sp+1);
>  	char **argv_orig = argv;
>  	char **envp = argv+argc+1;
> +	int replace_argv = 0;
>  
>  	/* Find aux vector just past environ[] and use it to initialize
>  	 * global data that may be needed before we can make syscalls. */
> @@ -1771,6 +1772,8 @@ void __dls3(size_t *sp, size_t *auxv)
>  				if (opt[5]=='=') replace_argv0 = opt+6;
>  				else if (opt[5]) *argv = 0;
>  				else if (*argv) replace_argv0 = *argv++;
> +			} else if (!memcmp(opt, "replace-argv", 12)) {
> +				replace_argv = 1;
>  			} else {
>  				argv[0] = 0;
>  			}
> @@ -1949,6 +1952,22 @@ void __dls3(size_t *sp, size_t *auxv)
>  	debug.state = 0;
>  	_dl_debug_state();
>  
> +	if (replace_argv) {
> +		char *argv_end = argv_orig[0];
> +		char *orig_ptr = argv_orig[0];
> +		int i;
> +		for (i = 0; i < (int)(argc - (argv-argv_orig)); i++) {
> +			char *src = (i == 0 && replace_argv0) ? replace_argv0 : argv[i];
> +			int len = strlen(src) + 1;
> +			memmove(orig_ptr, src, len);
> +			argv_end = argv[i] + strlen(argv[i]);
> +			argv[i] = orig_ptr;
> +			orig_ptr += len;
> +		}
> +		for (; orig_ptr < argv_end; orig_ptr++)
> +			*orig_ptr = 0;
> +	}
> +
>  	if (replace_argv0) argv[0] = replace_argv0;
>  
>  	errno = 0;
> -- 
> 2.7.4

Can you clarify what the purpose of this patch/option is? It seems
unrelated to the rest of the series and looks like it's doing
something really sketchy. It looks like it's making assumption about
the layout of the original strings, which is not an interface
contract, and like it happily overflows and clobbers unrelated memory
if replace_argv0 is longer than the original string pointed to by
argv[0].

Rich

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [musl] [PATCH 3/4] ldso: move (un)map_library functions to separate file
  2020-03-29  0:19 ` [musl] [PATCH 3/4] ldso: move (un)map_library functions to separate file rcombs
@ 2020-03-29  3:07   ` Rich Felker
  0 siblings, 0 replies; 6+ messages in thread
From: Rich Felker @ 2020-03-29  3:07 UTC (permalink / raw)
  To: musl

On Sat, Mar 28, 2020 at 07:19:27PM -0500, rcombs wrote:
> ---
>  ldso/dynlink.c     | 270 +--------------------------------------------------
>  ldso/map_library.h | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 278 insertions(+), 268 deletions(-)
>  create mode 100644 ldso/map_library.h
> 
> diff --git a/ldso/dynlink.c b/ldso/dynlink.c
> index 5f637fd..0e557b1 100644
> --- a/ldso/dynlink.c
> +++ b/ldso/dynlink.c
> @@ -154,6 +154,8 @@ extern hidden void (*const __init_array_end)(void), (*const __fini_array_end)(vo
>  weak_alias(__init_array_start, __init_array_end);
>  weak_alias(__fini_array_start, __fini_array_end);
>  
> +#include "map_library.h"
> +

As discussed before, I'd rather just duplicate the relevant part of
map_library for dcrt1 than refactor dynlink.c like this. There's a lot
of nommu logic that you don't have ready to work for dcrt1, and the
presence of that code is obscuring the fact that the operation dcrt1
needs is extremely simple. Also, there are a lot of shims (in patch 4)
to fake dynamic linker interfaces and libc functions for the shared
map_library.h code to use, which make the reuse clunky.

I think at some point it might be possible to factor things
sufficiently so that map_library is completely decoupled from dynamic
linker interfaces and able to be shared between these two components,
but your dcrt1 work has already been held up for around a year and I'd
like it to be able to move forward without depending on any
refactoring.

Would you like me to propose a stripped-down/decoupled version of the
function that dcrt1 could use?

Rich

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-03-29  3:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-29  0:19 [musl] [PATCH 1/4] ldso: add option to rewrite the argv block rcombs
2020-03-29  0:19 ` [musl] [PATCH 2/4] ldso: when run via CLI, set auxv as if the app was loaded by the kernel rcombs
2020-03-29  0:19 ` [musl] [PATCH 3/4] ldso: move (un)map_library functions to separate file rcombs
2020-03-29  3:07   ` Rich Felker
2020-03-29  0:19 ` [musl] [PATCH 4/4] crt: add dcrt1, with support for locating the dynamic loader at runtime rcombs
2020-03-29  2:54 ` [musl] [PATCH 1/4] ldso: add option to rewrite the argv block Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

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 NNTP newsgroup(s).