|
|
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.