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

Add fdlopen as specified and implemented in FreeBSD (see fdlopen(3) in
the FreeBSD manpages).

Signed-off-by: Pedro Falcato <pedro.falcato@...il.com>
---
 include/dlfcn.h    |  1 +
 ldso/dynlink.c     | 43 +++++++++++++++++++++++++++++++++++++++----
 src/ldso/fdlopen.c | 10 ++++++++++
 3 files changed, 50 insertions(+), 4 deletions(-)
 create mode 100644 src/ldso/fdlopen.c

diff --git a/include/dlfcn.h b/include/dlfcn.h
index 13ab71dd..6a01106d 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -33,6 +33,7 @@ typedef struct {
 } Dl_info;
 int dladdr(const void *, Dl_info *);
 int dlinfo(void *, int, void *);
+void *fdlopen(int, int);
 #endif
 
 #if _REDIR_TIME64
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 2272b768..161dde52 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -2040,7 +2040,7 @@ static void prepare_lazy(struct dso *p)
 	lazy_head = p;
 }
 
-void *dlopen(const char *file, int mode)
+static void *dlopen_internal(int fd, const char *file, int mode)
 {
 	struct dso *volatile p, *orig_tail, *orig_syms_tail, *orig_lazy_head, *next;
 	struct tls_module *orig_tls_tail;
@@ -2050,8 +2050,6 @@ void *dlopen(const char *file, int mode)
 	jmp_buf jb;
 	struct dso **volatile ctor_queue = 0;
 
-	if (!file) return head;
-
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
 	pthread_rwlock_wrlock(&lock);
 	__inhibit_ptc();
@@ -2104,7 +2102,32 @@ void *dlopen(const char *file, int mode)
 		tail->next = 0;
 		p = 0;
 		goto end;
-	} else p = load_library(file, head);
+	} else {
+		if (fd != -1) {
+			/* We were called from fdlopen. First, we must dup the fd (as FreeBSD does). */
+			fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
+			if (fd < 0) {
+				error("Failed to duplicate file descriptor: %m");
+				goto end;
+			}
+
+			/* Now try to figure out the path using procfs. If we fail, use a fallback. */
+			char path[PATH_MAX + 1];
+			const char *pathname = path;
+
+			__procfdname(path, fd);
+			ssize_t st = readlink(path, path, PATH_MAX);
+			if (st < 0) {
+				pathname = "<anon_fdlopen>";
+			} else {
+				path[st] = '\0';
+			}
+
+			p = load_library_core(fd, head, pathname, pathname);
+		} else {
+			p = load_library(file, head);
+		}
+	}
 
 	if (!p) {
 		error(noload ?
@@ -2167,6 +2190,18 @@ end:
 	return p;
 }
 
+void *fdlopen(int fd, int mode)
+{
+	if (fd == -1) return head;
+	return dlopen_internal(fd, 0, mode);
+}
+
+void *dlopen(const char *file, int mode)
+{
+	if (!file) return head;
+	return dlopen_internal(-1, file, mode);
+}
+
 hidden int __dl_invalid_handle(void *h)
 {
 	struct dso *p;
diff --git a/src/ldso/fdlopen.c b/src/ldso/fdlopen.c
new file mode 100644
index 00000000..a9380b57
--- /dev/null
+++ b/src/ldso/fdlopen.c
@@ -0,0 +1,10 @@
+#include <dlfcn.h>
+#include "dynlink.h"
+
+static void *stub_fdlopen(int fd, int mode)
+{
+	__dl_seterr("Dynamic loading not supported");
+	return 0;
+}
+
+weak_alias(stub_fdlopen, fdlopen);
-- 
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.