1 1.27 joerg /* $NetBSD: search.c,v 1.27 2020/04/22 23:54:32 joerg Exp $ */ 2 1.1 cgd 3 1.1 cgd /* 4 1.1 cgd * Copyright 1996 Matt Thomas <matt (at) 3am-software.com> 5 1.1 cgd * All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.1 cgd * 3. All advertising materials mentioning features or use of this software 16 1.1 cgd * must display the following acknowledgement: 17 1.1 cgd * This product includes software developed by John Polstra. 18 1.1 cgd * 4. The name of the author may not be used to endorse or promote products 19 1.1 cgd * derived from this software without specific prior written permission. 20 1.1 cgd * 21 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 1.1 cgd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 1.1 cgd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 1.1 cgd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 1.1 cgd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 1.1 cgd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 1.1 cgd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 1.1 cgd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 1.1 cgd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 1.1 cgd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 1.1 cgd */ 32 1.1 cgd 33 1.1 cgd /* 34 1.1 cgd * Dynamic linker for ELF. 35 1.1 cgd * 36 1.1 cgd * John Polstra <jdp (at) polstra.com>. 37 1.1 cgd */ 38 1.1 cgd 39 1.19 skrll #include <sys/cdefs.h> 40 1.19 skrll #ifndef lint 41 1.27 joerg __RCSID("$NetBSD: search.c,v 1.27 2020/04/22 23:54:32 joerg Exp $"); 42 1.19 skrll #endif /* not lint */ 43 1.19 skrll 44 1.1 cgd #include <err.h> 45 1.1 cgd #include <errno.h> 46 1.1 cgd #include <fcntl.h> 47 1.1 cgd #include <stdarg.h> 48 1.1 cgd #include <stdio.h> 49 1.1 cgd #include <stdlib.h> 50 1.1 cgd #include <string.h> 51 1.1 cgd #include <unistd.h> 52 1.1 cgd #include <sys/types.h> 53 1.1 cgd #include <sys/mman.h> 54 1.1 cgd #include <sys/stat.h> 55 1.1 cgd #include <dirent.h> 56 1.1 cgd 57 1.1 cgd #include "debug.h" 58 1.1 cgd #include "rtld.h" 59 1.7 hannken 60 1.1 cgd /* 61 1.1 cgd * Data declarations. 62 1.1 cgd */ 63 1.27 joerg static Search_Path *_rtld_invalid_paths; 64 1.14 junyoung 65 1.17 skrll static Obj_Entry *_rtld_search_library_path(const char *, size_t, 66 1.17 skrll const char *, size_t, int); 67 1.1 cgd 68 1.11 mycroft static Obj_Entry * 69 1.17 skrll _rtld_search_library_path(const char *name, size_t namelen, 70 1.23 skrll const char *dir, size_t dirlen, int flags) 71 1.1 cgd { 72 1.21 christos char pathname[MAXPATHLEN]; 73 1.14 junyoung size_t pathnamelen; 74 1.11 mycroft Obj_Entry *obj; 75 1.14 junyoung Search_Path *sp; 76 1.14 junyoung 77 1.14 junyoung pathnamelen = dirlen + 1 + namelen; 78 1.21 christos if (pathnamelen >= sizeof(pathname)) 79 1.21 christos return NULL; 80 1.1 cgd 81 1.14 junyoung for (sp = _rtld_invalid_paths; sp != NULL; sp = sp->sp_next) { 82 1.14 junyoung if (sp->sp_pathlen == pathnamelen && 83 1.22 joerg sp->sp_path[dirlen] == '/' && 84 1.15 mycroft !memcmp(name, sp->sp_path + dirlen + 1, namelen) && 85 1.15 mycroft !memcmp(dir, sp->sp_path, dirlen)) { 86 1.14 junyoung return NULL; 87 1.14 junyoung } 88 1.14 junyoung } 89 1.14 junyoung 90 1.22 joerg memcpy(pathname, dir, dirlen); 91 1.3 cgd pathname[dirlen] = '/'; 92 1.22 joerg memcpy(pathname + dirlen + 1, name, namelen); 93 1.22 joerg pathname[pathnamelen] = '\0'; 94 1.3 cgd 95 1.4 christos dbg((" Trying \"%s\"", pathname)); 96 1.23 skrll obj = _rtld_load_object(pathname, flags); 97 1.14 junyoung if (obj == NULL) { 98 1.14 junyoung Search_Path *path; 99 1.14 junyoung 100 1.14 junyoung path = NEW(Search_Path); 101 1.14 junyoung path->sp_pathlen = pathnamelen; 102 1.21 christos path->sp_path = xstrdup(pathname); 103 1.14 junyoung path->sp_next = _rtld_invalid_paths; 104 1.14 junyoung _rtld_invalid_paths = path; 105 1.14 junyoung } 106 1.11 mycroft return obj; 107 1.1 cgd } 108 1.4 christos 109 1.1 cgd /* 110 1.1 cgd * Find the library with the given name, and return its full pathname. 111 1.1 cgd * The returned string is dynamically allocated. Generates an error 112 1.1 cgd * message and returns NULL if the library cannot be found. 113 1.1 cgd * 114 1.1 cgd * If the second argument is non-NULL, then it refers to an already- 115 1.1 cgd * loaded shared object, whose library search path will be searched. 116 1.1 cgd */ 117 1.11 mycroft Obj_Entry * 118 1.23 skrll _rtld_load_library(const char *name, const Obj_Entry *refobj, int flags) 119 1.1 cgd { 120 1.25 christos extern char *__progname; 121 1.16 nathanw char tmperror[512], *tmperrorp; 122 1.4 christos Search_Path *sp; 123 1.21 christos const char *pathname; 124 1.4 christos int namelen; 125 1.11 mycroft Obj_Entry *obj; 126 1.4 christos 127 1.4 christos if (strchr(name, '/') != NULL) { /* Hard coded pathname */ 128 1.4 christos if (name[0] != '/' && !_rtld_trust) { 129 1.4 christos _rtld_error( 130 1.13 mycroft "absolute pathname required for shared object \"%s\"", 131 1.4 christos name); 132 1.4 christos return NULL; 133 1.4 christos } 134 1.21 christos pathname = name; 135 1.12 mycroft goto found; 136 1.1 cgd } 137 1.4 christos dbg((" Searching for \"%s\" (%p)", name, refobj)); 138 1.1 cgd 139 1.18 skrll tmperrorp = dlerror(); 140 1.16 nathanw if (tmperrorp != NULL) { 141 1.26 mrg strlcpy(tmperror, tmperrorp, sizeof(tmperror)); 142 1.16 nathanw tmperrorp = tmperror; 143 1.16 nathanw } 144 1.24 skrll 145 1.3 cgd namelen = strlen(name); 146 1.3 cgd 147 1.5 kleink for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next) 148 1.11 mycroft if ((obj = _rtld_search_library_path(name, namelen, 149 1.23 skrll sp->sp_path, sp->sp_pathlen, flags)) != NULL) 150 1.16 nathanw goto pathfound; 151 1.5 kleink 152 1.4 christos if (refobj != NULL) 153 1.4 christos for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next) 154 1.11 mycroft if ((obj = _rtld_search_library_path(name, 155 1.23 skrll namelen, sp->sp_path, sp->sp_pathlen, flags)) != NULL) 156 1.16 nathanw goto pathfound; 157 1.3 cgd 158 1.5 kleink for (sp = _rtld_default_paths; sp != NULL; sp = sp->sp_next) 159 1.11 mycroft if ((obj = _rtld_search_library_path(name, namelen, 160 1.23 skrll sp->sp_path, sp->sp_pathlen, flags)) != NULL) 161 1.16 nathanw goto pathfound; 162 1.3 cgd 163 1.25 christos _rtld_error("%s: Shared object \"%s\" not found", 164 1.25 christos refobj ? refobj->path : __progname, name); 165 1.4 christos return NULL; 166 1.16 nathanw 167 1.16 nathanw pathfound: 168 1.16 nathanw /* 169 1.23 skrll * The library has been found, but it couldn't be loaded for some 170 1.23 skrll * reason. 171 1.23 skrll */ 172 1.23 skrll if (obj == OBJ_ERR) 173 1.23 skrll return NULL; 174 1.23 skrll /* 175 1.16 nathanw * Successfully found a library; restore the dlerror state as it was 176 1.16 nathanw * before _rtld_load_library() was called (any failed call to 177 1.16 nathanw * _rtld_search_library_path() will set the dlerror state, but if the 178 1.16 nathanw * library was eventually found, then the error state should not 179 1.16 nathanw * change. 180 1.16 nathanw */ 181 1.16 nathanw if (tmperrorp) 182 1.16 nathanw _rtld_error("%s", tmperror); 183 1.16 nathanw else 184 1.18 skrll (void)dlerror(); 185 1.16 nathanw return obj; 186 1.11 mycroft 187 1.12 mycroft found: 188 1.23 skrll obj = _rtld_load_object(pathname, flags); 189 1.23 skrll if (obj == OBJ_ERR) 190 1.23 skrll return NULL; 191 1.23 skrll 192 1.23 skrll return obj; 193 1.1 cgd } 194 1.23 skrll 195