From 2ec718ef2f5794c67bdfed8fd915033d472f21e5 Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Wed, 1 Feb 2023 12:56:35 -0800 Subject: [PATCH] Run dlmopen in a child process. --- tools/elfdeps.c | 56 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/tools/elfdeps.c b/tools/elfdeps.c index 0e37a248a1..52fda172fe 100644 --- a/tools/elfdeps.c +++ b/tools/elfdeps.c @@ -72,24 +72,60 @@ static char *getLibtoolVer(const char *filename) } break; } else { - return NULL; + break; } } return NULL; } +/* + * Rather than re-implement path searching for shared objects, use + * dlmopen(). This will still perform initialization and finalization + * functions, which isn't necessarily safe, so do that in a separate + * process. + */ static char *getLibtoolVerFromShLink(const char *filename) { - void *dl_handle; - struct link_map *linkmap; - char *version = NULL; - dl_handle = dlmopen(LM_ID_NEWLM, filename, RTLD_LAZY); - if (dl_handle == NULL) return NULL; - if (dlinfo(dl_handle, RTLD_DI_LINKMAP, &linkmap) != -1) { - version = getLibtoolVer(linkmap->l_name); + char dest[PATH_MAX]; + int pipefd[2]; + pid_t cpid; + + if (pipe(pipefd) == -1) { + return NULL; // Should this be a fatal error instead? + } + cpid = fork(); + if (cpid == -1) { + return NULL; // Should this be a fatal error instead? + } + if (cpid == 0) { + void *dl_handle; + struct link_map *linkmap; + char *version = NULL; + + close(pipefd[0]); + dl_handle = dlmopen(LM_ID_NEWLM, filename, RTLD_LAZY); + if (dl_handle == NULL) _exit(0); + if (dlinfo(dl_handle, RTLD_DI_LINKMAP, &linkmap) != -1) { + version = getLibtoolVer(linkmap->l_name); + } + write(pipefd[1], version, strlen(version)); + close(pipefd[1]); + free(version); + dlclose(dl_handle); + _exit(0); + } else { + ssize_t len; + close(pipefd[1]); + dest[0] = 0; + len = read(pipefd[0], dest, sizeof(dest)); + if (len > 0) dest[len] = 0; + close(pipefd[0]); + wait(NULL); } - dlclose(dl_handle); - return version; + if (strlen(dest) > 0) + return strdup(dest); + else + return NULL; } /*