Home | History | Annotate | Line # | Download | only in ld.elf_so
symver.c revision 1.1.8.1
      1      1.1  nonaka /*	$NetBSD: symver.c,v 1.1.8.1 2013/06/23 06:28:50 tls 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.1  nonaka __RCSID("$NetBSD: symver.c,v 1.1.8.1 2013/06/23 06:28:50 tls 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.1.8.1     tls void
     72  1.1.8.1     tls _rtld_object_add_name(Obj_Entry *obj, const char *name)
     73  1.1.8.1     tls {
     74  1.1.8.1     tls     Name_Entry *entry;
     75  1.1.8.1     tls     size_t len;
     76  1.1.8.1     tls 
     77  1.1.8.1     tls     len = strlen(name);
     78  1.1.8.1     tls     entry = xmalloc(sizeof(Name_Entry) + len);
     79  1.1.8.1     tls 
     80  1.1.8.1     tls     if (entry != NULL) {
     81  1.1.8.1     tls 	strcpy(entry->name, name);
     82  1.1.8.1     tls 	SIMPLEQ_INSERT_TAIL(&obj->names, entry, link);
     83  1.1.8.1     tls     }
     84  1.1.8.1     tls }
     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.1.8.1     tls 	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.1.8.1     tls #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.1.8.1     tls #endif
    334