1 1.4 christos /* $NetBSD: symver.c,v 1.4 2013/05/09 15:38:14 christos Exp $ */ 2 1.1 nonaka 3 1.1 nonaka /*- 4 1.1 nonaka * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 5 1.1 nonaka * Copyright 2003 Alexander Kabaev <kan (at) FreeBSD.ORG>. 6 1.1 nonaka * Copyright 2009, 2010, 2011 Konstantin Belousov <kib (at) FreeBSD.ORG>. 7 1.1 nonaka * All rights reserved. 8 1.1 nonaka * 9 1.1 nonaka * Redistribution and use in source and binary forms, with or without 10 1.1 nonaka * modification, are permitted provided that the following conditions 11 1.1 nonaka * are met: 12 1.1 nonaka * 1. Redistributions of source code must retain the above copyright 13 1.1 nonaka * notice, this list of conditions and the following disclaimer. 14 1.1 nonaka * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 nonaka * notice, this list of conditions and the following disclaimer in the 16 1.1 nonaka * documentation and/or other materials provided with the distribution. 17 1.1 nonaka * 18 1.1 nonaka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.1 nonaka * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 nonaka * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.1 nonaka * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 nonaka * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.1 nonaka * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 nonaka * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 nonaka * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 nonaka * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.1 nonaka * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 nonaka * 29 1.1 nonaka * $FreeBSD: head/libexec/rtld-elf/rtld.c 220004 2011-03-25 18:23:10Z avg $ 30 1.1 nonaka */ 31 1.1 nonaka 32 1.1 nonaka /*- 33 1.1 nonaka * Copyright (c) 2011 The NetBSD Foundation, Inc. 34 1.1 nonaka * All rights reserved. 35 1.1 nonaka * 36 1.1 nonaka * This code is derived from software contributed to The NetBSD Foundation 37 1.1 nonaka * by NONAKA Kimihiro. 38 1.1 nonaka * 39 1.1 nonaka * Redistribution and use in source and binary forms, with or without 40 1.1 nonaka * modification, are permitted provided that the following conditions 41 1.1 nonaka * are met: 42 1.1 nonaka * 1. Redistributions of source code must retain the above copyright 43 1.1 nonaka * notice, this list of conditions and the following disclaimer. 44 1.1 nonaka * 2. Redistributions in binary form must reproduce the above copyright 45 1.1 nonaka * notice, this list of conditions and the following disclaimer in the 46 1.1 nonaka * documentation and/or other materials provided with the distribution. 47 1.1 nonaka * 48 1.1 nonaka * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 49 1.1 nonaka * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 50 1.1 nonaka * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 51 1.1 nonaka * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 52 1.1 nonaka * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 53 1.1 nonaka * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 54 1.1 nonaka * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 55 1.1 nonaka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 56 1.1 nonaka * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 57 1.1 nonaka * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 58 1.1 nonaka * POSSIBILITY OF SUCH DAMAGE. 59 1.1 nonaka */ 60 1.1 nonaka 61 1.1 nonaka #include <sys/cdefs.h> 62 1.4 christos __RCSID("$NetBSD: symver.c,v 1.4 2013/05/09 15:38:14 christos Exp $"); 63 1.1 nonaka 64 1.1 nonaka #include <sys/param.h> 65 1.1 nonaka #include <sys/exec_elf.h> 66 1.1 nonaka #include <string.h> 67 1.1 nonaka 68 1.1 nonaka #include "debug.h" 69 1.1 nonaka #include "rtld.h" 70 1.1 nonaka 71 1.2 christos void 72 1.2 christos _rtld_object_add_name(Obj_Entry *obj, const char *name) 73 1.2 christos { 74 1.2 christos Name_Entry *entry; 75 1.2 christos size_t len; 76 1.2 christos 77 1.2 christos len = strlen(name); 78 1.2 christos entry = xmalloc(sizeof(Name_Entry) + len); 79 1.2 christos 80 1.2 christos if (entry != NULL) { 81 1.2 christos strcpy(entry->name, name); 82 1.4 christos SIMPLEQ_INSERT_TAIL(&obj->names, entry, link); 83 1.2 christos } 84 1.2 christos } 85 1.1 nonaka 86 1.1 nonaka int 87 1.1 nonaka _rtld_object_match_name(const Obj_Entry *obj, const char *name) 88 1.1 nonaka { 89 1.1 nonaka Name_Entry *entry; 90 1.1 nonaka 91 1.4 christos SIMPLEQ_FOREACH(entry, &obj->names, link) { 92 1.1 nonaka dbg(("name: %s, entry->name: %s", name, entry->name)); 93 1.1 nonaka if (strcmp(name, entry->name) == 0) 94 1.1 nonaka return 1; 95 1.1 nonaka } 96 1.1 nonaka return 0; 97 1.1 nonaka } 98 1.1 nonaka 99 1.3 christos #ifdef RTLD_LOADER 100 1.1 nonaka static Obj_Entry * 101 1.1 nonaka locate_dependency(const Obj_Entry *obj, const char *name) 102 1.1 nonaka { 103 1.1 nonaka const Objlist_Entry *entry; 104 1.1 nonaka const Needed_Entry *needed; 105 1.1 nonaka 106 1.1 nonaka SIMPLEQ_FOREACH(entry, &_rtld_list_main, link) { 107 1.1 nonaka if (_rtld_object_match_name(entry->obj, name)) 108 1.1 nonaka return entry->obj; 109 1.1 nonaka } 110 1.1 nonaka 111 1.1 nonaka for (needed = obj->needed; needed != NULL; needed = needed->next) { 112 1.1 nonaka dbg(("needed: name: %s, str: %s", name, 113 1.1 nonaka &obj->strtab[needed->name])); 114 1.1 nonaka if (strcmp(name, &obj->strtab[needed->name]) == 0 || 115 1.1 nonaka (needed->obj != NULL && _rtld_object_match_name(needed->obj, name))) { 116 1.1 nonaka /* 117 1.1 nonaka * If there is DT_NEEDED for the name we are looking 118 1.1 nonaka * for, we are all set. Note that object might not be 119 1.1 nonaka * found if dependency was not loaded yet, so the 120 1.1 nonaka * function can return NULL here. This is expected 121 1.1 nonaka * and handled properly by the caller. 122 1.1 nonaka */ 123 1.1 nonaka return needed->obj; 124 1.1 nonaka } 125 1.1 nonaka } 126 1.1 nonaka 127 1.1 nonaka _rtld_error("%s: Unexpected inconsistency: dependency %s not found", 128 1.1 nonaka obj->path, name); 129 1.1 nonaka return NULL; 130 1.1 nonaka } 131 1.1 nonaka 132 1.1 nonaka static int 133 1.1 nonaka check_object_provided_version(Obj_Entry *refobj, const Obj_Entry *depobj, 134 1.1 nonaka const Elf_Vernaux *vna) 135 1.1 nonaka { 136 1.1 nonaka const char *vername = &refobj->strtab[vna->vna_name]; 137 1.1 nonaka const char *depstrtab = depobj->strtab; 138 1.1 nonaka const Elf_Verdef *vd = depobj->verdef; 139 1.1 nonaka const Elf_Word hash = vna->vna_hash; 140 1.1 nonaka 141 1.1 nonaka if (vd == NULL) { 142 1.1 nonaka _rtld_error("%s: version %s required by %s not defined", 143 1.1 nonaka depobj->path, vername, refobj->path); 144 1.1 nonaka return -1; 145 1.1 nonaka } 146 1.1 nonaka 147 1.1 nonaka for (;; vd = (const Elf_Verdef *)((const char *)vd + vd->vd_next)) { 148 1.1 nonaka if (vd->vd_version != VER_DEF_CURRENT) { 149 1.1 nonaka _rtld_error( 150 1.1 nonaka "%s: Unsupported version %d of Elf_Verdef entry", 151 1.1 nonaka depobj->path, vd->vd_version); 152 1.1 nonaka return -1; 153 1.1 nonaka } 154 1.1 nonaka dbg(("hash: 0x%x, vd_hash: 0x%x", hash, vd->vd_hash)); 155 1.1 nonaka if (hash == vd->vd_hash) { 156 1.1 nonaka const Elf_Verdaux *vda = (const Elf_Verdaux *) 157 1.1 nonaka ((const char *)vd + vd->vd_aux); 158 1.1 nonaka dbg(("vername: %s, str: %s", vername, 159 1.1 nonaka &depstrtab[vda->vda_name])); 160 1.1 nonaka if (strcmp(vername, &depstrtab[vda->vda_name]) == 0) 161 1.1 nonaka return 0; 162 1.1 nonaka } 163 1.1 nonaka if (vd->vd_next == 0) 164 1.1 nonaka break; 165 1.1 nonaka } 166 1.1 nonaka if (vna->vna_flags & VER_FLG_WEAK) 167 1.1 nonaka return 0; 168 1.1 nonaka 169 1.1 nonaka _rtld_error("%s: version %s required by %s not found", depobj->path, 170 1.1 nonaka vername, refobj->path); 171 1.1 nonaka return -1; 172 1.1 nonaka } 173 1.1 nonaka 174 1.1 nonaka int 175 1.1 nonaka _rtld_verify_object_versions(Obj_Entry *obj) 176 1.1 nonaka { 177 1.1 nonaka const char *strtab = obj->strtab; 178 1.1 nonaka const Elf_Verneed *vn; 179 1.1 nonaka const Elf_Vernaux *vna; 180 1.1 nonaka const Elf_Verdef *vd; 181 1.1 nonaka const Elf_Verdaux *vda; 182 1.1 nonaka const Obj_Entry *depobj; 183 1.1 nonaka int maxvertab, vernum; 184 1.1 nonaka 185 1.1 nonaka dbg(("obj->path: %s", obj->path)); 186 1.1 nonaka 187 1.1 nonaka /* 188 1.1 nonaka * If we don't have string table or objects that have their version 189 1.1 nonaka * requirements already checked, we must be ok. 190 1.1 nonaka */ 191 1.1 nonaka if (strtab == NULL || obj->vertab != NULL) 192 1.1 nonaka return 0; 193 1.1 nonaka 194 1.1 nonaka maxvertab = 0; 195 1.1 nonaka 196 1.1 nonaka /* 197 1.1 nonaka * Walk over defined and required version records and figure out 198 1.1 nonaka * max index used by any of them. Do very basic sanity checking 199 1.1 nonaka * while there. 200 1.1 nonaka */ 201 1.1 nonaka for (vn = obj->verneed; 202 1.1 nonaka vn != NULL; 203 1.1 nonaka vn = (const Elf_Verneed *)((const char *)vn + vn->vn_next)) { 204 1.1 nonaka 205 1.1 nonaka if (vn->vn_version != VER_NEED_CURRENT) { 206 1.1 nonaka _rtld_error( 207 1.1 nonaka "%s: Unsupported version %d of Elf_Verneed entry", 208 1.1 nonaka obj->path, vn->vn_version); 209 1.1 nonaka return -1; 210 1.1 nonaka } 211 1.1 nonaka 212 1.1 nonaka dbg(("verneed: vn_file: %d, str: %s", 213 1.1 nonaka vn->vn_file, &strtab[vn->vn_file])); 214 1.1 nonaka depobj = locate_dependency(obj, &strtab[vn->vn_file]); 215 1.1 nonaka assert(depobj != NULL); 216 1.1 nonaka 217 1.1 nonaka for (vna = (const Elf_Vernaux *)((const char *)vn + vn->vn_aux); 218 1.1 nonaka /*CONSTCOND*/1; 219 1.1 nonaka vna = (const Elf_Vernaux *)((const char *)vna + vna->vna_next)) { 220 1.1 nonaka 221 1.1 nonaka if (check_object_provided_version(obj, depobj, vna) == -1) 222 1.1 nonaka return -1; 223 1.1 nonaka 224 1.1 nonaka vernum = VER_NEED_IDX(vna->vna_other); 225 1.1 nonaka if (vernum > maxvertab) 226 1.1 nonaka maxvertab = vernum; 227 1.1 nonaka 228 1.1 nonaka if (vna->vna_next == 0) { 229 1.1 nonaka /* No more symbols. */ 230 1.1 nonaka break; 231 1.1 nonaka } 232 1.1 nonaka } 233 1.1 nonaka 234 1.1 nonaka if (vn->vn_next == 0) { 235 1.1 nonaka /* No more dependencies. */ 236 1.1 nonaka break; 237 1.1 nonaka } 238 1.1 nonaka } 239 1.1 nonaka 240 1.1 nonaka for (vd = obj->verdef; 241 1.1 nonaka vd != NULL; 242 1.1 nonaka vd = (const Elf_Verdef *)((const char *)vd + vd->vd_next)) { 243 1.1 nonaka 244 1.1 nonaka if (vd->vd_version != VER_DEF_CURRENT) { 245 1.1 nonaka _rtld_error( 246 1.1 nonaka "%s: Unsupported version %d of Elf_Verdef entry", 247 1.1 nonaka obj->path, vd->vd_version); 248 1.1 nonaka return -1; 249 1.1 nonaka } 250 1.1 nonaka 251 1.1 nonaka dbg(("verdef: vn_ndx: 0x%x", vd->vd_ndx)); 252 1.1 nonaka vernum = VER_DEF_IDX(vd->vd_ndx); 253 1.1 nonaka if (vernum > maxvertab) 254 1.1 nonaka maxvertab = vernum; 255 1.1 nonaka 256 1.1 nonaka if (vd->vd_next == 0) { 257 1.1 nonaka /* No more definitions. */ 258 1.1 nonaka break; 259 1.1 nonaka } 260 1.1 nonaka } 261 1.1 nonaka 262 1.1 nonaka dbg(("maxvertab: %d", maxvertab)); 263 1.1 nonaka if (maxvertab == 0) 264 1.1 nonaka return 0; 265 1.1 nonaka 266 1.1 nonaka /* 267 1.1 nonaka * Store version information in array indexable by version index. 268 1.1 nonaka * Verify that object version requirements are satisfied along the 269 1.1 nonaka * way. 270 1.1 nonaka */ 271 1.1 nonaka obj->vertabnum = maxvertab + 1; 272 1.1 nonaka obj->vertab = (Ver_Entry *)xcalloc(obj->vertabnum * sizeof(Ver_Entry)); 273 1.1 nonaka 274 1.1 nonaka for (vn = obj->verneed; 275 1.1 nonaka vn != NULL; 276 1.1 nonaka vn = (const Elf_Verneed *)((const char *)vn + vn->vn_next)) { 277 1.1 nonaka 278 1.1 nonaka for (vna = (const Elf_Vernaux *)((const char *)vn + vn->vn_aux); 279 1.1 nonaka /*CONSTCOND*/1; 280 1.1 nonaka vna = (const Elf_Vernaux *)((const char *)vna + vna->vna_next)) { 281 1.1 nonaka 282 1.1 nonaka vernum = VER_NEED_IDX(vna->vna_other); 283 1.1 nonaka assert(vernum <= maxvertab); 284 1.1 nonaka obj->vertab[vernum].hash = vna->vna_hash; 285 1.1 nonaka obj->vertab[vernum].name = &strtab[vna->vna_name]; 286 1.1 nonaka obj->vertab[vernum].file = &strtab[vn->vn_file]; 287 1.1 nonaka obj->vertab[vernum].flags = 288 1.1 nonaka (vna->vna_other & VER_NEED_HIDDEN) 289 1.1 nonaka ? VER_INFO_HIDDEN : 0; 290 1.1 nonaka dbg(("verneed: vernum: %d, hash: 0x%x, name: %s, " 291 1.1 nonaka "file: %s, flags: 0x%x", vernum, 292 1.1 nonaka obj->vertab[vernum].hash, obj->vertab[vernum].name, 293 1.1 nonaka obj->vertab[vernum].file, 294 1.1 nonaka obj->vertab[vernum].flags)); 295 1.1 nonaka 296 1.1 nonaka if (vna->vna_next == 0) { 297 1.1 nonaka /* No more symbols. */ 298 1.1 nonaka break; 299 1.1 nonaka } 300 1.1 nonaka } 301 1.1 nonaka if (vn->vn_next == 0) { 302 1.1 nonaka /* No more dependencies. */ 303 1.1 nonaka break; 304 1.1 nonaka } 305 1.1 nonaka } 306 1.1 nonaka 307 1.1 nonaka for (vd = obj->verdef; 308 1.1 nonaka vd != NULL; 309 1.1 nonaka vd = (const Elf_Verdef *)((const char *)vd + vd->vd_next)) { 310 1.1 nonaka 311 1.1 nonaka if ((vd->vd_flags & VER_FLG_BASE) == 0) { 312 1.1 nonaka vernum = VER_DEF_IDX(vd->vd_ndx); 313 1.1 nonaka assert(vernum <= maxvertab); 314 1.1 nonaka vda = (const Elf_Verdaux *) 315 1.1 nonaka ((const char *)vd + vd->vd_aux); 316 1.1 nonaka obj->vertab[vernum].hash = vd->vd_hash; 317 1.1 nonaka obj->vertab[vernum].name = &strtab[vda->vda_name]; 318 1.1 nonaka obj->vertab[vernum].file = NULL; 319 1.1 nonaka obj->vertab[vernum].flags = 0; 320 1.1 nonaka dbg(("verdef: vernum: %d, hash: 0x%x, name: %s", 321 1.1 nonaka vernum, obj->vertab[vernum].hash, 322 1.1 nonaka obj->vertab[vernum].name)); 323 1.1 nonaka } 324 1.1 nonaka 325 1.1 nonaka if (vd->vd_next == 0) { 326 1.1 nonaka /* No more definitions. */ 327 1.1 nonaka break; 328 1.1 nonaka } 329 1.1 nonaka } 330 1.1 nonaka 331 1.1 nonaka return 0; 332 1.1 nonaka } 333 1.3 christos #endif 334