Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230508181413.194379-2-pedro.falcato@gmail.com>
Date: Mon,  8 May 2023 19:14:12 +0100
From: Pedro Falcato <pedro.falcato@...il.com>
To: musl@...ts.openwall.com
Cc: Pedro Falcato <pedro.falcato@...il.com>
Subject: [RFC PATCH 1/2] dynlink: Reorganize library loading

Separate the core of library loading from load_library, in a way that
can be reused by codepaths that do not need path -> library resolution.

Signed-off-by: Pedro Falcato <pedro.falcato@...il.com>
---
 ldso/dynlink.c | 202 ++++++++++++++++++++++++++-----------------------
 1 file changed, 107 insertions(+), 95 deletions(-)

diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 2b8c382b..2272b768 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -988,16 +988,118 @@ static void makefuncdescs(struct dso *p)
 	}
 }
 
+static struct dso *load_library(const char *name, struct dso *needed_by);
+
+static struct dso *load_library_core(int fd, struct dso *needed_by, const char *pathname, const char *name)
+{
+	struct dso *p;
+	struct stat st;
+	size_t alloc_size;
+	int n_th = 0;
+	unsigned char *map;
+	struct dso temp_dso = {0};
+
+	if (fd < 0) return 0;
+	if (fstat(fd, &st) < 0) {
+		close(fd);
+		return 0;
+	}
+	for (p=head->next; p; p=p->next) {
+		if (p->dev == st.st_dev && p->ino == st.st_ino) {
+			/* If this library was previously loaded with a
+			 * pathname but a search found the same inode,
+			 * setup its shortname so it can be found by name. */
+			if (!p->shortname && pathname != name)
+				p->shortname = strrchr(p->name, '/')+1;
+			close(fd);
+			return p;
+		}
+	}
+	map = noload ? 0 : map_library(fd, &temp_dso);
+	close(fd);
+	if (!map) return 0;
+
+	/* Avoid the danger of getting two versions of libc mapped into the
+	 * same process when an absolute pathname was used. The symbols
+	 * checked are chosen to catch both musl and glibc, and to avoid
+	 * false positives from interposition-hack libraries. */
+	decode_dyn(&temp_dso);
+	if (find_sym(&temp_dso, "__libc_start_main", 1).sym &&
+	    find_sym(&temp_dso, "stdin", 1).sym) {
+		unmap_library(&temp_dso);
+		return load_library("libc.so", needed_by);
+	}
+	/* Past this point, if we haven't reached runtime yet, ldso has
+	 * committed either to use the mapped library or to abort execution.
+	 * Unmapping is not possible, so we can safely reclaim gaps. */
+	if (!runtime) reclaim_gaps(&temp_dso);
+
+	/* Allocate storage for the new DSO. When there is TLS, this
+	 * storage must include a reservation for all pre-existing
+	 * threads to obtain copies of both the new TLS, and an
+	 * extended DTV capable of storing an additional slot for
+	 * the newly-loaded DSO. */
+	alloc_size = sizeof *p + strlen(pathname) + 1;
+	if (runtime && temp_dso.tls.image) {
+		size_t per_th = temp_dso.tls.size + temp_dso.tls.align
+			+ sizeof(void *) * (tls_cnt+3);
+		n_th = libc.threads_minus_1 + 1;
+		if (n_th > SSIZE_MAX / per_th) alloc_size = SIZE_MAX;
+		else alloc_size += n_th * per_th;
+	}
+	p = calloc(1, alloc_size);
+	if (!p) {
+		unmap_library(&temp_dso);
+		return 0;
+	}
+	memcpy(p, &temp_dso, sizeof temp_dso);
+	p->dev = st.st_dev;
+	p->ino = st.st_ino;
+	p->needed_by = needed_by;
+	p->name = p->buf;
+	p->runtime_loaded = runtime;
+	strcpy(p->name, pathname);
+	/* Add a shortname only if name arg was not an explicit pathname. */
+	if (pathname != name) p->shortname = strrchr(p->name, '/')+1;
+	if (p->tls.image) {
+		p->tls_id = ++tls_cnt;
+		tls_align = MAXP2(tls_align, p->tls.align);
+#ifdef TLS_ABOVE_TP
+		p->tls.offset = tls_offset + ( (p->tls.align-1) &
+			(-tls_offset + (uintptr_t)p->tls.image) );
+		tls_offset = p->tls.offset + p->tls.size;
+#else
+		tls_offset += p->tls.size + p->tls.align - 1;
+		tls_offset -= (tls_offset + (uintptr_t)p->tls.image)
+			& (p->tls.align-1);
+		p->tls.offset = tls_offset;
+#endif
+		p->new_dtv = (void *)(-sizeof(size_t) &
+			(uintptr_t)(p->name+strlen(p->name)+sizeof(size_t)));
+		p->new_tls = (void *)(p->new_dtv + n_th*(tls_cnt+1));
+		if (tls_tail) tls_tail->next = &p->tls;
+		else libc.tls_head = &p->tls;
+		tls_tail = &p->tls;
+	}
+
+	tail->next = p;
+	p->prev = tail;
+	tail = p;
+
+	if (DL_FDPIC) makefuncdescs(p);
+
+	if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, p->base);
+
+	return p;
+}
+
 static struct dso *load_library(const char *name, struct dso *needed_by)
 {
 	char buf[2*NAME_MAX+2];
 	const char *pathname;
-	unsigned char *map;
-	struct dso *p, temp_dso = {0};
+	struct dso *p;
 	int fd;
 	struct stat st;
-	size_t alloc_size;
-	int n_th = 0;
 	int is_self = 0;
 
 	if (!*name) {
@@ -1100,98 +1202,8 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 		}
 		pathname = buf;
 	}
-	if (fd < 0) return 0;
-	if (fstat(fd, &st) < 0) {
-		close(fd);
-		return 0;
-	}
-	for (p=head->next; p; p=p->next) {
-		if (p->dev == st.st_dev && p->ino == st.st_ino) {
-			/* If this library was previously loaded with a
-			 * pathname but a search found the same inode,
-			 * setup its shortname so it can be found by name. */
-			if (!p->shortname && pathname != name)
-				p->shortname = strrchr(p->name, '/')+1;
-			close(fd);
-			return p;
-		}
-	}
-	map = noload ? 0 : map_library(fd, &temp_dso);
-	close(fd);
-	if (!map) return 0;
-
-	/* Avoid the danger of getting two versions of libc mapped into the
-	 * same process when an absolute pathname was used. The symbols
-	 * checked are chosen to catch both musl and glibc, and to avoid
-	 * false positives from interposition-hack libraries. */
-	decode_dyn(&temp_dso);
-	if (find_sym(&temp_dso, "__libc_start_main", 1).sym &&
-	    find_sym(&temp_dso, "stdin", 1).sym) {
-		unmap_library(&temp_dso);
-		return load_library("libc.so", needed_by);
-	}
-	/* Past this point, if we haven't reached runtime yet, ldso has
-	 * committed either to use the mapped library or to abort execution.
-	 * Unmapping is not possible, so we can safely reclaim gaps. */
-	if (!runtime) reclaim_gaps(&temp_dso);
-
-	/* Allocate storage for the new DSO. When there is TLS, this
-	 * storage must include a reservation for all pre-existing
-	 * threads to obtain copies of both the new TLS, and an
-	 * extended DTV capable of storing an additional slot for
-	 * the newly-loaded DSO. */
-	alloc_size = sizeof *p + strlen(pathname) + 1;
-	if (runtime && temp_dso.tls.image) {
-		size_t per_th = temp_dso.tls.size + temp_dso.tls.align
-			+ sizeof(void *) * (tls_cnt+3);
-		n_th = libc.threads_minus_1 + 1;
-		if (n_th > SSIZE_MAX / per_th) alloc_size = SIZE_MAX;
-		else alloc_size += n_th * per_th;
-	}
-	p = calloc(1, alloc_size);
-	if (!p) {
-		unmap_library(&temp_dso);
-		return 0;
-	}
-	memcpy(p, &temp_dso, sizeof temp_dso);
-	p->dev = st.st_dev;
-	p->ino = st.st_ino;
-	p->needed_by = needed_by;
-	p->name = p->buf;
-	p->runtime_loaded = runtime;
-	strcpy(p->name, pathname);
-	/* Add a shortname only if name arg was not an explicit pathname. */
-	if (pathname != name) p->shortname = strrchr(p->name, '/')+1;
-	if (p->tls.image) {
-		p->tls_id = ++tls_cnt;
-		tls_align = MAXP2(tls_align, p->tls.align);
-#ifdef TLS_ABOVE_TP
-		p->tls.offset = tls_offset + ( (p->tls.align-1) &
-			(-tls_offset + (uintptr_t)p->tls.image) );
-		tls_offset = p->tls.offset + p->tls.size;
-#else
-		tls_offset += p->tls.size + p->tls.align - 1;
-		tls_offset -= (tls_offset + (uintptr_t)p->tls.image)
-			& (p->tls.align-1);
-		p->tls.offset = tls_offset;
-#endif
-		p->new_dtv = (void *)(-sizeof(size_t) &
-			(uintptr_t)(p->name+strlen(p->name)+sizeof(size_t)));
-		p->new_tls = (void *)(p->new_dtv + n_th*(tls_cnt+1));
-		if (tls_tail) tls_tail->next = &p->tls;
-		else libc.tls_head = &p->tls;
-		tls_tail = &p->tls;
-	}
-
-	tail->next = p;
-	p->prev = tail;
-	tail = p;
-
-	if (DL_FDPIC) makefuncdescs(p);
 
-	if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, p->base);
-
-	return p;
+	return load_library_core(fd, needed_by, pathname, name);
 }
 
 static void load_direct_deps(struct dso *p)
-- 
2.40.1

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.