diff options
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/ld.so/ldconfig/Makefile | 4 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/debug.c | 159 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/ldconfig.8 | 30 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/ldconfig.c | 28 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/ldconfig_path.c (renamed from libexec/ld.so/ldconfig/prebind_path.c) | 2 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/library.c | 310 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/prebind.c | 2311 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/prebind.h | 68 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/prebind_delete.c | 301 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/prebind_struct.h | 86 |
10 files changed, 8 insertions, 3291 deletions
diff --git a/libexec/ld.so/ldconfig/Makefile b/libexec/ld.so/ldconfig/Makefile index 4bce223c723..588e85fc566 100644 --- a/libexec/ld.so/ldconfig/Makefile +++ b/libexec/ld.so/ldconfig/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.11 2014/07/06 17:33:10 otto Exp $ +# $OpenBSD: Makefile,v 1.12 2016/07/04 20:56:50 kettenis Exp $ # $NetBSD: Makefile,v 1.10 1995/03/06 04:24:41 cgd Exp $ MAN= ldconfig.8 @@ -6,7 +6,7 @@ MAN= ldconfig.8 .include <bsd.own.mk> PROG= ldconfig -SRCS= ldconfig.c shlib.c etc.c prebind_delete.c debug.c prebind.c library.c sod.c prebind_path.c +SRCS= ldconfig.c shlib.c etc.c sod.c ldconfig_path.c LDDIR?= $(.CURDIR)/.. CFLAGS+=-Wall CFLAGS+=-I$(.CURDIR) -I$(.CURDIR)/.. diff --git a/libexec/ld.so/ldconfig/debug.c b/libexec/ld.so/ldconfig/debug.c deleted file mode 100644 index 550dac032e3..00000000000 --- a/libexec/ld.so/ldconfig/debug.c +++ /dev/null @@ -1,159 +0,0 @@ -/* $OpenBSD: debug.c,v 1.6 2015/01/16 16:18:07 deraadt Exp $ */ -/* - * Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <limits.h> -#include <fcntl.h> -#include <nlist.h> -#include <elf_abi.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <dirent.h> -#include "resolve.h" -#include "link.h" -#include "sod.h" -#ifndef __mips64__ -#include "machine/reloc.h" -#endif -#include "prebind.h" -#include "prebind_struct.h" - -#ifdef DEBUG1 -void -dump_info(struct elf_object *object) -{ - int numrel, numrela, i; - const Elf_Sym *symt; - const char *strt; - Elf_Word *needed_list; - - symt = object->dyn.symtab; - strt = object->dyn.strtab; - - for (i = 0; i < object->nchains; i++) { - const Elf_Sym *sym = symt + i; - char *type; - - switch (ELF_ST_TYPE(sym->st_info)) { - case STT_FUNC: - type = "func"; - break; - case STT_OBJECT: - type = "object"; - break; - case STT_NOTYPE: - type = "notype"; - break; - default: - type = "UNKNOWN"; - } - printf("symbol %d [%s] type %s value %x\n", i, - strt + sym->st_name, - type, sym->st_value); - } - - numrel = object->dyn.relsz / sizeof(Elf_Rel); - numrela = object->dyn.relasz / sizeof(Elf_RelA); - printf("numrel %d numrela %d\n", numrel, numrela); - - printf("rel relocations:\n"); - for (i = 0; i < numrel ; i++) { - Elf_Rel *rel = object->dyn.rel; - - printf("%d: %x sym %x type %d\n", i, rel[i].r_offset, - ELF_R_SYM(rel[i].r_info), ELF_R_TYPE(rel[i].r_info)); - } - printf("rela relocations:\n"); - for (i = 0; i < numrela ; i++) { - Elf_RelA *rela = object->dyn.rela; - - printf("%d: %x sym %x type %d\n", i, rela[i].r_offset, - ELF_R_SYM(rela[i].r_info), ELF_R_TYPE(rela[i].r_info)); - } - needed_list = (Elf_Addr *)object->dyn.needed; - for (i = 0; needed_list[i] != NULL; i++) - printf("NEEDED %s\n", needed_list[i] + strt); - -} -#endif - - -void -elf_dump_footer(struct prebind_footer *footer) -{ - printf("\nbase %llx\n", (long long)footer->prebind_base); - printf("nameidx_idx %d\n", footer->nameidx_idx); - printf("symcache_idx %d\n", footer->symcache_idx); - printf("pltsymcache_idx %d\n", footer->pltsymcache_idx); - printf("fixupcnt_idx %d\n", footer->fixupcnt_idx); - printf("fixup_cnt %d\n", footer->fixup_cnt); - printf("nametab_idx %d\n", footer->nametab_idx); - printf("symcache_cnt %d\n", footer->symcache_cnt); - printf("pltsymcache_cnt %d\n", footer->pltsymcache_cnt); - printf("fixup_cnt %d\n", footer->fixup_cnt); - printf("numlibs %d\n", footer->numlibs); - printf("id0 %x\n", footer->id0); - printf("id1 %x\n", footer->id1); - printf("orig_size %lld\n", (long long)footer->orig_size); - printf("version %d\n", footer->prebind_version); - printf("bind_id %c%c%c%c\n", footer->bind_id[0], - footer->bind_id[1], footer->bind_id[2], footer->bind_id[3]); -} - - -void -dump_symcachetab(struct symcachetab *symcachetab, int symcache_cnt, - struct elf_object *object, int id) -{ - int i; - - printf("symcache for %s\n", object->load_name); - for (i = 0; i < symcache_cnt; i++) { - printf("symidx %d: obj %d sym %d\n", - symcachetab[i].idx, - symcachetab[i].obj_idx, - symcachetab[i].sym_idx); - } -} - -void -elf_print_prog_list(prog_list_ty *prog_list) -{ - struct elf_object *object; - struct proglist *pl; - - TAILQ_FOREACH(pl, prog_list, list) { - object = TAILQ_FIRST(&(pl->curbin_list))->object; - printf("bin: %s\n", object->load_name); - elf_print_curbin_list(pl); - } -} - -void -elf_print_curbin_list(struct proglist *bin) -{ - struct objlist *ol; - - TAILQ_FOREACH(ol, &(bin->curbin_list), list) { - printf("\t%s\n", ol->object->load_name); - } -} - diff --git a/libexec/ld.so/ldconfig/ldconfig.8 b/libexec/ld.so/ldconfig/ldconfig.8 index 57080495d5a..48dd3c86828 100644 --- a/libexec/ld.so/ldconfig/ldconfig.8 +++ b/libexec/ld.so/ldconfig/ldconfig.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ldconfig.8,v 1.28 2015/04/28 14:07:16 jmc Exp $ +.\" $OpenBSD: ldconfig.8,v 1.29 2016/07/04 20:56:50 kettenis Exp $ .\" .\" Copyright (c) 1993,1995 Paul Kranenburg .\" All rights reserved. @@ -29,7 +29,7 @@ .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" -.Dd $Mdocdate: April 28 2015 $ +.Dd $Mdocdate: July 4 2016 $ .Dt LDCONFIG 8 .Os .Sh NAME @@ -37,7 +37,7 @@ .Nd configure the shared library cache .Sh SYNOPSIS .Nm ldconfig -.Op Fl DmPRrSsUv +.Op Fl mRrsUv .Op Ar path ... .Sh DESCRIPTION .Nm @@ -91,18 +91,12 @@ for further information. The following options are recognized by .Nm ldconfig : .Bl -tag -width indent -.It Fl D -Remove any prebind information in the specified binary or shared library. .It Fl m Merge the result of the scan of the directories given as arguments into the existing hints file. The default action is to build the hints file afresh. This option cannot be used with .Fl U . -.It Fl P -Create and append prebind information to all executables found in -the specified directories, and also all shared libraries which are -required by those executables. .It Fl R Rescan the previously configured directories. This opens the hints file and fetches the directory list from the header. @@ -112,12 +106,6 @@ List the current contents of .Pa ld.so.hints on the standard output. The hints file will not be modified. -.It Fl S -Prebind safely: always copies the binaries -when prebind information is added to a file. -Use this to eliminate the possibility that -.Dv ETXTBUSY -will occur when attempting to run a binary whilst prebinding. .It Fl s Do not scan the built-in system directory .Pq Dq /usr/lib @@ -130,18 +118,6 @@ This option cannot be used with .It Fl v Switch on verbose mode. .El -.Sh PREBINDING -When prebind information is added to libraries and programs using -.Fl P , -program startup can be significantly improved because -.Xr ld.so 1 -can initialize the shared library environment much faster. -Prebind information adds a small amount of data to the end of each -specified program and associated shared libraries. -Prebinding is loosely based on an earlier concept called prelinking, which -also accelerated -.Xr ld.so 1 -performance but simultaneously impaired address space randomization. .Sh SECURITY Special care must be taken when loading shared libraries into the address space of diff --git a/libexec/ld.so/ldconfig/ldconfig.c b/libexec/ld.so/ldconfig/ldconfig.c index 28909689a15..1badc8ca32d 100644 --- a/libexec/ld.so/ldconfig/ldconfig.c +++ b/libexec/ld.so/ldconfig/ldconfig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ldconfig.c,v 1.35 2015/11/15 02:49:59 deraadt Exp $ */ +/* $OpenBSD: ldconfig.c,v 1.36 2016/07/04 20:56:50 kettenis Exp $ */ /* * Copyright (c) 1993,1995 Paul Kranenburg @@ -49,8 +49,6 @@ #include <unistd.h> #include <limits.h> -#include "prebind.h" - #include "ld.h" #undef major @@ -59,12 +57,9 @@ extern char *__progname; int verbose; -static int delete; -static int doprebind; static int nostd; static int justread; int merge; -int safe; static int rescan; static int unconfig; @@ -92,7 +87,7 @@ static void usage(void) { fprintf(stderr, - "usage: %s [-DmPRrSsUv] [path ...]\n", __progname); + "usage: %s [-mRrsUv] [path ...]\n", __progname); exit(1); } @@ -122,18 +117,9 @@ main(int argc, char *argv[]) case 's': nostd = 1; break; - case 'S': - safe = 1; - break; case 'v': verbose = 1; break; - case 'D': - delete = 1; - break; - case 'P': - doprebind = 1; - break; default: usage(); break; @@ -159,16 +145,6 @@ main(int argc, char *argv[]) } else if (!nostd) std_search_path(); - if (delete) { - if (rescan || unconfig || merge || justread || nostd || doprebind) - errx(1, "cannot mix -U -R -r -s -P options with -D"); - exit(prebind_delete(&argv[optind])); - } else if (doprebind) { - if (rescan || unconfig || justread || nostd) - errx(1, "cannot mix other options with -P"); - exit(prebind(&argv[optind])); - } - if (unconfig) { if (optind < argc) for (i = optind; i < argc; i++) diff --git a/libexec/ld.so/ldconfig/prebind_path.c b/libexec/ld.so/ldconfig/ldconfig_path.c index 31a2a0eb1a3..fdd803d33a4 100644 --- a/libexec/ld.so/ldconfig/prebind_path.c +++ b/libexec/ld.so/ldconfig/ldconfig_path.c @@ -1,4 +1,4 @@ -/* $OpenBSD: prebind_path.c,v 1.4 2015/08/23 06:27:32 deraadt Exp $ */ +/* $OpenBSD: ldconfig_path.c,v 1.1 2016/07/04 20:56:50 kettenis Exp $ */ /* * Copyright (c) 2013 Kurt Miller <kurt@intricatesoftware.com> diff --git a/libexec/ld.so/ldconfig/library.c b/libexec/ld.so/ldconfig/library.c deleted file mode 100644 index 771d9b5c510..00000000000 --- a/libexec/ld.so/ldconfig/library.c +++ /dev/null @@ -1,310 +0,0 @@ -/* $OpenBSD: library.c,v 1.10 2015/09/06 08:44:07 tobias Exp $ */ -/* - * Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <limits.h> -#include <fcntl.h> -#include <nlist.h> -#include <elf_abi.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> -#include <dirent.h> -#include "link.h" -#include "sod.h" -#include "resolve.h" -#include "prebind.h" -#include "prebind_struct.h" - -char *_dl_default_path[2] = { "/usr/lib", NULL }; - -elf_object_t *elf_load_shlib_hint(struct sod *sod, struct sod *req_sod, - int ignore_hints, char **libpath); -char *elf_find_shlib(struct sod *sodp, char **searchpath, int nohints); -elf_object_t * elf_tryload_shlib(const char *libname); -int elf_match_file(struct sod *sodp, char *name, int namelen); -int load_lib(const char *, struct elf_object *); - -int -load_lib(const char *name, struct elf_object *parent) -{ - struct sod sod, req_sod; - int ignore_hints, try_any_minor = 0; - struct elf_object *object = NULL; - -#if 0 - printf("load_lib %s\n", name); -#endif - ignore_hints = 0; - - if(strchr(name, '/')) { - char *paths[2]; - char *lpath, *lname; - - lpath = strdup(name); - if (lpath == NULL) - return (1); - lname = strrchr(lpath, '/'); - if (lname == NULL || lname[1] == '\0') { - free(lpath); - return (1); /* failed */ - } - *lname = '\0'; - lname++; - - _dl_build_sod(lname, &sod); - req_sod = sod; - - paths[0] = lpath; - paths[1] = NULL; - /* this code does not allow lower minors */ -fullpathagain: - object = elf_load_shlib_hint(&sod, &req_sod, - ignore_hints, paths); - if (object != NULL) - goto fullpathdone; - - if (try_any_minor == 0) { - try_any_minor = 1; - ignore_hints = 1; - req_sod.sod_minor = -1; - goto fullpathagain; - } - /* ERR */ -fullpathdone: - free(lpath); - free((char *)sod.sod_name); - return (object == NULL); /* failed */ - } - _dl_build_sod(name, &sod); - req_sod = sod; - - /* ignore LD_LIBRARY_PATH */ - -again: - if (parent->rpath != NULL) { - object = elf_load_shlib_hint(&sod, &req_sod, - ignore_hints, parent->rpath); - if (object != NULL) - goto done; - } - if (parent != load_object && load_object->rpath != NULL) { - object = elf_load_shlib_hint(&sod, &req_sod, - ignore_hints, load_object->rpath); - if (object != NULL) - goto done; - } - object = elf_load_shlib_hint(&sod, &req_sod, ignore_hints, NULL); - - if (try_any_minor == 0) { - try_any_minor = 1; - ignore_hints = 1; - req_sod.sod_minor = -1; - goto again; - } - if (object == NULL) - printf ("unable to load %s\n", name); - -done: - free((char *)sod.sod_name); - - return (object == NULL); -} - -/* - * attempt to locate and load a library based on libpath, sod info and - * if it needs to respect hints, passing type and flags to perform open - */ -elf_object_t * -elf_load_shlib_hint(struct sod *sod, struct sod *req_sod, - int ignore_hints, char **libpath) -{ - elf_object_t *object = NULL; - char *hint; - - hint = elf_find_shlib(req_sod, libpath, ignore_hints); - if (hint != NULL) { - if (req_sod->sod_minor < sod->sod_minor) - printf("warning: lib%s.so.%d.%d: " - "minor version >= %d expected, " - "using it anyway\n", - (char *)sod->sod_name, sod->sod_major, - req_sod->sod_minor, sod->sod_minor); - object = elf_tryload_shlib(hint); - } - return object; -} - -char elf_hint_store[PATH_MAX]; - -char * -elf_find_shlib(struct sod *sodp, char **searchpath, int nohints) -{ - char *hint, **pp; - struct sod tsod, bsod; /* transient and best sod */ - struct dirent *dp; - int match, len; - DIR *dd; - - /* if we are to search default directories, and hints - * are not to be used, search the standard path from ldconfig - * (_dl_hint_search_path) or use the default path - */ - if (nohints) - goto nohints; - - if (searchpath == NULL) { - /* search 'standard' locations, find any match in the hints */ - hint = _dl_findhint((char *)sodp->sod_name, sodp->sod_major, - sodp->sod_minor, NULL); - if (hint) - return hint; - } else { - /* search hints requesting matches for only - * the searchpath directories, - */ - for (pp = searchpath; *pp != NULL; pp++) { - hint = _dl_findhint((char *)sodp->sod_name, - sodp->sod_major, sodp->sod_minor, *pp); - if (hint != NULL) - return hint; - } - } - - /* - * For each directory in the searchpath, read the directory - * entries looking for a match to sod. filename compare is - * done by _dl_match_file() - */ -nohints: - if (searchpath == NULL) { - if (_dl_hint_search_path != NULL) - searchpath = _dl_hint_search_path; - else - searchpath = _dl_default_path; - } - memset(&bsod, 0, sizeof(bsod)); - for (pp = searchpath; *pp != NULL; pp++) { - if ((dd = opendir(*pp)) != NULL) { - match = 0; - while ((dp = readdir(dd)) != NULL) { - tsod = *sodp; - if (elf_match_file(&tsod, dp->d_name, - dp->d_namlen)) { - /* - * When a match is found, tsod is - * updated with the major+minor found. - * This version is compared with the - * largest so far (kept in bsod), - * and saved if larger. - */ - if (!match || - tsod.sod_major == -1 || - tsod.sod_major > bsod.sod_major || - ((tsod.sod_major == - bsod.sod_major) && - tsod.sod_minor > bsod.sod_minor)) { - bsod = tsod; - match = 1; - len = strlcpy( - elf_hint_store, *pp, - PATH_MAX); - if (pp[0][len-1] != '/') { - elf_hint_store[len] = - '/'; - len++; - } - strlcpy( - &elf_hint_store[len], - dp->d_name, - PATH_MAX-len); - if (tsod.sod_major == -1) - break; - } - } - } - closedir(dd); - if (match) { - *sodp = bsod; - return (elf_hint_store); - } - } - } - return NULL; -} - -elf_object_t * -elf_tryload_shlib(const char *libname) -{ - struct elf_object *object; - object = elf_lookup_object(libname); - - if (object == NULL) - object = load_file(libname, OBJTYPE_LIB); - if (object == NULL) - printf("tryload_shlib %s\n", libname); - return object; -} - -/* - * elf_match_file() - * - * This function determines if a given name matches what is specified - * in a struct sod. The major must match exactly, and the minor must - * be same or larger. - * - * sodp is updated with the minor if this matches. - */ - -int -elf_match_file(struct sod *sodp, char *name, int namelen) -{ - int match; - struct sod lsod; - char *lname; - - lname = name; - if (sodp->sod_library) { - if (strncmp(name, "lib", 3)) - return 0; - lname += 3; - } - if (strncmp(lname, (char *)sodp->sod_name, - strlen((char *)sodp->sod_name))) - return 0; - - _dl_build_sod(name, &lsod); - - match = 0; - if (strcmp((char *)lsod.sod_name, (char *)sodp->sod_name) == 0 && - lsod.sod_library == sodp->sod_library && - (sodp->sod_major == -1 || sodp->sod_major == lsod.sod_major) && - (sodp->sod_minor == -1 || lsod.sod_minor >= sodp->sod_minor)) { - match = 1; - - /* return version matched */ - sodp->sod_major = lsod.sod_major; - sodp->sod_minor = lsod.sod_minor; - } - free((char *)lsod.sod_name); - return match; -} - diff --git a/libexec/ld.so/ldconfig/prebind.c b/libexec/ld.so/ldconfig/prebind.c deleted file mode 100644 index 978a9a71498..00000000000 --- a/libexec/ld.so/ldconfig/prebind.c +++ /dev/null @@ -1,2311 +0,0 @@ -/* $OpenBSD: prebind.c,v 1.34 2016/05/11 21:52:49 deraadt Exp $ */ -/* - * Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <limits.h> -#include <errno.h> -#include <fcntl.h> -#include <nlist.h> -#include <elf_abi.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <dirent.h> -#include <err.h> -#include "resolve.h" -#include "link.h" -#include "path.h" -#include "sod.h" -#ifndef __mips64__ -#include "machine/reloc.h" -#endif -#include "prebind.h" -#include "ld.h" - -/* seems to make sense to limit how big of file can be dealt with */ -#define MAX_FILE_SIZE (512 * 1024 * 1024) - -char *shstrtab; - -/* alpha uses RELOC_JMP_SLOT */ -#ifdef __amd64__ -#define RELOC_JMP_SLOT R_X86_64_JUMP_SLOT -#endif -#ifdef __arm__ -#define RELOC_JMP_SLOT R_ARM_JUMP_SLOT -#endif -#ifdef __hppa__ -#define RELOC_JMP_SLOT RELOC_IPLT -#endif -#ifdef __i386__ -#define RELOC_JMP_SLOT RELOC_JUMP_SLOT -#endif -#ifdef __sh__ -#define RELOC_JMP_SLOT R_SH_JMP_SLOT -#endif -#ifdef __mips64__ -#define RELOC_JMP_SLOT 0 /* XXX mips64 doesnt have PLT reloc */ -#endif -#ifdef __m88k__ -#define RELOC_JMP_SLOT RELOC_GOTP_ENT -#endif -#ifdef __vax__ -#define RELOC_JMP_SLOT R_VAX_JMP_SLOT -#endif -/* powerpc uses RELOC_JMP_SLOT */ -/* sparc uses RELOC_JMP_SLOT */ -/* sparc64 uses RELOC_JMP_SLOT */ - -#define BUFSZ (256 * 1024) - -#include "prebind_struct.h" -struct proglist *curbin; - -obj_list_ty library_list = - TAILQ_HEAD_INITIALIZER(library_list); - -prog_list_ty prog_list = - TAILQ_HEAD_INITIALIZER(prog_list); - -struct objarray_list { - struct elf_object *obj; - struct symcache_noflag *symcache; - struct symcache_noflag *pltsymcache; - struct proglist *proglist; - u_int32_t id0; - u_int32_t id1; - u_int32_t *idxtolib; - void *oprebind_data; - int numlibs; - - TAILQ_HEAD(, objlist) inst_list; -} *objarray; - - -struct prebind_info { - struct elf_object *object; - struct prebind_footer *footer; - u_int32_t footer_offset; - u_int32_t nfixup; - struct nameidx *nameidx; - struct symcachetab *symcache; - struct symcachetab *pltsymcache; - u_int32_t *fixuptab; - u_int32_t *fixupcnt; - struct fixup **fixup; - u_int32_t *maptab; - u_int32_t **libmap; - u_int32_t *libmapcnt; - char *nametab; - u_int32_t nametablen; -}; - -int objarray_cnt; -int objarray_sz; - -void copy_oldsymcache(int objidx, char *prebind_data); -void elf_load_existing_prebind(struct elf_object *object, int fd); -void insert_sym_objcache(struct elf_object *, int, - const struct elf_object *, const Elf_Sym *, int); - -struct elf_object * elf_load_object(void *pexe, const char *name); -void elf_free_object(struct elf_object *object); -void map_to_virt(Elf_Phdr *, Elf_Ehdr *, Elf_Addr, u_long *); -int load_obj_needed(struct elf_object *object); -int load_lib(const char *name, struct elf_object *parent); -elf_object_t * elf_load_shlib_hint(struct sod *sod, struct sod *req_sod, - int use_hints, const char *libpath); -char *elf_find_shlib(struct sod *sodp, const char *searchpath, - int nohints); -elf_object_t * elf_tryload_shlib(const char *libname); -int elf_match_file(struct sod *sodp, char *name, int namelen); -void elf_init_objarray(void); -void elf_add_object(struct elf_object *object, int objtype); -void elf_print_objarray(void); -void elf_reloc(struct elf_object *object); - -struct elf_object * elf_lookup_object(const char *name); -struct elf_object * elf_lookup_object_devino(dev_t dev, ino_t inode, - int objtype); -void elf_free_curbin_list(struct elf_object *obj); -void elf_resolve_curbin(void); -struct proglist *elf_newbin(void); -void elf_sum_reloc(void); -int elf_prep_lib_prebind(struct elf_object *object); -int elf_prep_bin_prebind(struct proglist *pl); -void add_fixup_prog(struct elf_object *prog, struct elf_object *obj, int idx, - const struct elf_object *ref_obj, const Elf_Sym *ref_sym, int flag); -void add_fixup_oldprog(struct elf_object *prog, struct elf_object *obj, - int idx, const struct elf_object *ref_obj, const Elf_Sym *ref_sym, - int flag); - -void elf_dump_footer(struct prebind_footer *footer); - -void elf_fixup_prog_load(int fd, struct prebind_footer *footer, - struct elf_object *object); -void elf_clear_prog_load(int fd, struct elf_object *object); - -void elf_find_symbol_rel(const char *s, struct elf_object *object, - Elf_Rel *rel, struct symcache_noflag *symcache, - struct symcache_noflag *pltsymcache); - -void elf_find_symbol_rela(const char *s, struct elf_object *object, - Elf_RelA *rela, struct symcache_noflag *symcache, - struct symcache_noflag *pltsymcache); - -int elf_find_symbol_obj(elf_object_t *object, const char *name, - unsigned long hash, int flags, const Elf_Sym **this, - const Elf_Sym **weak_sym, elf_object_t **weak_object); - -int prebind_writefile(int fd, struct prebind_info *info); -int prebind_writenewfile(int infd, char *name, struct stat *st, off_t orig_size, - struct prebind_info *info); - -struct elf_object *load_object; - -struct elf_object *load_file(const char *filename, int lib); -int elf_check_note(void *buf, Elf_Phdr *phdr); -void load_file_or_dir(char *name); -void load_dir(char *name); -void load_exe(char *name); - -int -prebind(char **argv) -{ - int i; - - elf_init_objarray(); - - for (i = 0; argv[i]; i++) - load_file_or_dir(argv[i]); - - if (verbose > 4) { - elf_print_objarray(); - elf_print_prog_list(&prog_list); - } - elf_sum_reloc(); - - return (0); -} - -/* - * load ELF objects at the specified path it could be - * either a either a directory or file, if the object is - * a file, attempt to load it as an executable (will ignore shared objects - * and any files that are not Elf execuables. - * if the object is a directory pass it to a routine to deal with - * directory parsing. - */ -void -load_file_or_dir(char *name) -{ - struct stat sb; - int ret; - - ret = lstat(name, &sb); - if (ret != 0) - return; - switch (sb.st_mode & S_IFMT) { - case S_IFREG: - load_exe(name); - break; - case S_IFDIR: - if (verbose > 0) - printf("loading dir %s\n", name); - load_dir(name); - break; - default: - ; /* links and other files we skip */ - } - -} - -/* - * for all of the objects in the directory, if it is a regular file - * load it as a binary, if it is unknown (nfs mount) stat the file - * and load the file for S_IFREG - * any other type of directory object: symlink, directory, socket, ... - * is ignored. - */ -void -load_dir(char *name) -{ - struct dirent *dp; - struct stat sb; - DIR *dirp; - char *buf; - - dirp = opendir(name); - - /* if dir failed to open, skip */ - if (dirp == NULL) - return; - - while ((dp = readdir(dirp)) != NULL) { - switch (dp->d_type) { - case DT_UNKNOWN: - /* - * NFS will return unknown, since load_file - * does stat the file, this just - */ - if (asprintf(&buf, "%s/%s", name, dp->d_name) == -1) { - warn("asprintf"); - goto done; - } - lstat(buf, &sb); - if (sb.st_mode == S_IFREG) - load_exe(buf); - free(buf); - break; - case DT_REG: - if (asprintf(&buf, "%s/%s", name, dp->d_name) == -1) { - warn("asprintf"); - goto done; - } - load_exe(buf); - free(buf); - break; - default: - /* other files symlinks, dirs, ... we ignore */ - ; - } - } -done: - closedir(dirp); -} - -/* - * the given pathname is a regular file, however it may or may not - * be an ELF file. Attempt to load the given path and calculate prebind - * data for it. - * if the given file is not a ELF binary this will 'fail' and - * should not change any of the prebind state. - */ -void -load_exe(char *name) -{ - struct elf_object *object; - struct elf_object *interp; - struct objlist *ol; - int fail = 0; - - curbin = elf_newbin(); - if (verbose > 0) - printf("processing %s\n", name); - object = load_file(name, OBJTYPE_EXE); - if (object != NULL && load_object != NULL && - object->load_object == NULL) { - TAILQ_FOREACH(ol, &(curbin->curbin_list), list) { - fail = load_obj_needed(ol->object); - if (fail != 0) - break; /* XXX */ - - } - if (fail == 0) { - interp = load_file(curbin->interp, OBJTYPE_DLO); - object->load_object = interp; - if (interp == NULL) - fail = 1; - } - - /* slight abuse of this field */ - - if (fail == 0) { - objarray[object->dyn.null].proglist = curbin; - elf_resolve_curbin(); - TAILQ_INSERT_TAIL(&prog_list, curbin, list); - } else { - printf("failed to load %s\n", name); - elf_free_curbin_list(object); - free(curbin); - } - if (load_object != NULL) { - load_object = NULL; - } - } else { - free(curbin); - } -} - -/* - * given a path to a file, attempt to open it and load any data necessary - * for prebind. this function is used for executables, libraries and ld.so - * file, it will do a lookup on the dev/inode to use a cached version - * of the file if it was already loaded, in case a library is referenced - * by more than one program or there are hardlinks between executable names. - * if the file is not an elf file of the appropriate type, it will return - * failure. - */ -struct elf_object * -load_file(const char *filename, int objtype) -{ - struct elf_object *obj = NULL; - int fd = -1, i, note_found; - struct stat ifstat; - void *buf = NULL; - Elf_Ehdr *ehdr; - Elf_Shdr *shdr; - Elf_Phdr *phdr; - char *pexe; - - fd = open(filename, O_RDONLY); - if (fd == -1) { - perror(filename); - goto done; - } - - if (fstat(fd, &ifstat) == -1) { - perror(filename); - goto done; - } - - if ((ifstat.st_mode & S_IFMT) != S_IFREG) - goto done; - - if (ifstat.st_size < sizeof (Elf_Ehdr)) - goto done; - - obj = elf_lookup_object_devino(ifstat.st_dev, ifstat.st_ino, objtype); - if (obj != NULL) - goto done; - - buf = mmap(NULL, ifstat.st_size, PROT_READ, MAP_FILE | MAP_SHARED, - fd, 0); - if (buf == MAP_FAILED) { - printf("%s: cannot mmap\n", filename); - goto done; - } - - ehdr = (Elf_Ehdr *)buf; - - if (IS_ELF(*ehdr) == 0) - goto done; - - if (ehdr->e_machine != ELF_TARG_MACH) { - if (verbose > 0) - printf("%s: wrong arch\n", filename); - goto done; - } - - if (objtype == OBJTYPE_EXE) { - if (ehdr->e_type != ET_EXEC) - goto done; - - note_found = 0; - - phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff); - for (i = 0; i < ehdr->e_phnum; i++) { - if (phdr[i].p_type == PT_NOTE) { - note_found = elf_check_note(buf,&phdr[i]); - break; - } - } - if (note_found == 0) - goto done; /* no OpenBSD note found */ - } - - if ((objtype == OBJTYPE_LIB || objtype == OBJTYPE_DLO) && - (ehdr->e_type != ET_DYN)) - goto done; - - pexe = buf; - if (ehdr->e_shstrndx == 0) - goto done; - - shdr = (Elf_Shdr *)(pexe + ehdr->e_shoff + - (ehdr->e_shstrndx * ehdr->e_shentsize)); - - shstrtab = (char *)(pexe + shdr->sh_offset); - - obj = elf_load_object(pexe, filename); - - munmap(buf, ifstat.st_size); - buf = NULL; - - if (obj != NULL) { - obj->obj_type = objtype; - - obj->dev = ifstat.st_dev; - obj->inode = ifstat.st_ino; - if (load_object == NULL) - load_object = obj; - - elf_add_object(obj, objtype); - -#ifdef DEBUG1 - dump_info(obj); -#endif - } - if ((objtype == OBJTYPE_LIB || objtype == OBJTYPE_DLO) && - merge == 1) { - /* - * for libraries and dynamic linker, check if old prebind - * info exists and load it if we are in merge mode - */ - elf_load_existing_prebind(obj, fd); - } -done: - if (buf != NULL) - munmap(buf, ifstat.st_size); - if (fd != -1) - close(fd); - return obj; -} - -/* - * check if the given executable header on a ELF executable - * has the proper OpenBSD note on the file if it is not present - * binaries will be skipped. - */ -int -elf_check_note(void *buf, Elf_Phdr *phdr) -{ - u_long address; - u_int *pint; - char *osname; - - address = phdr->p_offset; - pint = (u_int *)((char *)buf + address); - osname = (char *)buf + address + sizeof(*pint) * 3; - - if (pint[0] == 8 /* OpenBSD\0 */ && - pint[1] == 4 /* ??? */ && - pint[2] == 1 /* type_osversion */ && - strcmp("OpenBSD", osname) == 0) - return 1; - - return 0; -} - -struct elf_object * -elf_load_object(void *pexe, const char *name) -{ - struct elf_object *object; - Elf_Dyn *dynp = NULL, *odynp; - Elf_Ehdr *ehdr; - Elf_Phdr *phdr; - Elf_Addr lbase; - Elf_Word *needed_list; - int needed_cnt = 0, i; - - object = calloc(1, sizeof (struct elf_object)); - if (object == NULL) { - printf("unable to allocate object for %s\n", name); - exit(10); - } - ehdr = pexe; - lbase = (Elf_Addr)pexe; - - object->load_base = lbase; - object->load_name = strdup(name); - if (object->load_name == NULL) { - printf("unable to allocate object for %s\n", name); - exit(10); - } - - phdr = (Elf_Phdr *)((char *)pexe + ehdr->e_phoff); - for (i = 0; i < ehdr->e_phnum; i++) { - switch (phdr[i].p_type) { - case PT_DYNAMIC: - dynp = (Elf_Dyn *)(phdr[i].p_offset); - break; - case PT_INTERP: - /* XXX can only occur in programs */ - curbin->interp = strdup((char *)((char *)pexe + - phdr[i].p_offset)); - if (curbin->interp == NULL) { - printf("unable to allocate object for %s\n", - name); - exit(10); - } - break; - default: - break; - } - } - - if (dynp == 0) { - free(object); - return NULL; /* not a dynamic binary */ - } - - dynp = (Elf_Dyn *)((unsigned long)dynp + lbase); - odynp = dynp; - while (dynp->d_tag != DT_NULL) { - if (dynp->d_tag < DT_NUM) - object->Dyn.info[dynp->d_tag] = dynp->d_un.d_val; - else if (dynp->d_tag >= DT_LOPROC && - dynp->d_tag < DT_LOPROC + DT_PROCNUM) - object->Dyn.info[dynp->d_tag + DT_NUM - DT_LOPROC] = - dynp->d_un.d_val; - if (dynp->d_tag == DT_TEXTREL) - object->dyn.textrel = 1; - if (dynp->d_tag == DT_SYMBOLIC) - object->dyn.symbolic = 1; - if (dynp->d_tag == DT_BIND_NOW) - object->obj_flags |= DF_1_NOW; - if (dynp->d_tag == DT_FLAGS_1) - object->obj_flags |= dynp->d_un.d_val; - if (dynp->d_tag == DT_NEEDED) - needed_cnt++; - - dynp++; - } - - needed_list = calloc((needed_cnt + 1), sizeof(Elf_Word)); - if (needed_list == NULL) { - printf("unable to allocate needed_list for %s\n", name); - exit(10); - } - needed_list[needed_cnt] = 0; - for (dynp = odynp, i = 0; dynp->d_tag != DT_NULL; dynp++) { - if (dynp->d_tag == DT_NEEDED) { - needed_list[i] = dynp->d_un.d_val; - i++; - } - } - - if (object->Dyn.info[DT_HASH]) - map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_HASH]); - if (object->Dyn.info[DT_STRTAB]) - map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_STRTAB]); - if (object->Dyn.info[DT_SYMTAB]) - map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_SYMTAB]); - - if (object->Dyn.info[DT_RELA]) - map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_RELA]); - if (object->Dyn.info[DT_RPATH]) - object->Dyn.info[DT_RPATH] += object->Dyn.info[DT_STRTAB]; - if (object->Dyn.info[DT_REL]) - map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_REL]); - if (object->Dyn.info[DT_JMPREL]) - map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_JMPREL]); - - { - Elf_Sym *sym; - char *str; - Elf_Rel *rel; - Elf_RelA *rela; - Elf_Addr *hash; - Elf_Word *hashtab; - void *plt; - size_t hashsz; - - if (object->Dyn.info[DT_HASH] != 0) { - hash = object->dyn.hash; - hashtab = (void *)hash; - object->nbuckets = hashtab[0]; - object->nchains = hashtab[1]; - hash = reallocarray(NULL, 2 + object->nbuckets - + object->nchains, sizeof(Elf_Word)); - if (hash == NULL) { - printf("unable to allocate hash for %s\n", - name); - exit(10); - } - hashsz = (2 + object->nbuckets + object->nchains) * - sizeof(Elf_Word); - - bcopy(object->dyn.hash, hash, hashsz); - object->dyn.hash = hash; - object->buckets = ((Elf_Word *)hash + 2); - object->chains = object->buckets + object->nbuckets; - } - - str = malloc(object->dyn.strsz); - if (str == NULL) { - printf("unable to allocate strtab for %s\n", - name); - exit(10); - } - bcopy(object->dyn.strtab, str, object->dyn.strsz); - object->dyn.strtab = str; - - sym = calloc(object->nchains, sizeof(Elf_Sym)); - if (sym == NULL) { - printf("unable to allocate symtab for %s\n", - name); - exit(10); - } - bcopy(object->dyn.symtab, sym, - object->nchains * sizeof(Elf_Sym)); - object->dyn.symtab = sym; - - if (object->dyn.relsz != 0) { - rel = malloc(object->dyn.relsz); - if (rel == NULL) { - printf("unable to allocate rel reloc for %s\n", - name); - exit(10); - } - bcopy(object->dyn.rel, rel, object->dyn.relsz); - object->dyn.rel = rel; - } else { - object->dyn.rel = NULL; - } - if (object->dyn.relasz != 0) { - rela = malloc(object->dyn.relasz); - if (rela == NULL) { - printf("unable to allocate rela reloc for %s\n", - name); - exit(10); - } - bcopy(object->dyn.rela, rela, object->dyn.relasz); - object->dyn.rela = rela; - } else { - object->dyn.rela = NULL; - } - if (object->dyn.pltrelsz != 0) { - plt = malloc(object->dyn.pltrelsz); - if (plt == NULL) { - printf("unable to allocate plt reloc for %s\n", - name); - exit(10); - } - bcopy((void*)object->dyn.jmprel, plt, - object->dyn.pltrelsz); - object->dyn.jmprel = (long)plt; - } else { - object->dyn.jmprel = 0; - } - if (object->dyn.rpath != NULL){ - object->rpath = _dl_split_path(object->dyn.rpath); - if (object->rpath == NULL) { - printf("unable to allocate rpath for %s\n", - name); - exit(10); - } - } - object->dyn.needed = (Elf_Addr)needed_list; - } - -#ifdef DEBUG1 - dump_info(object); -#endif - return object; -} - -/* - * Free any extra pieces associated with 'object' - */ -void -elf_free_object(struct elf_object *object) -{ - free(object->load_name); - free(object->dyn.hash); - free((void *)object->dyn.strtab); - free((void *)object->dyn.symtab); - free(object->dyn.rel); - free(object->dyn.rela); - if (object->dyn.rpath != NULL) - free((void *)object->dyn.rpath); - free(object); -} - -/* - * translate an object address into a file offset for the - * file assuming that the file is mapped at base. - */ -void -map_to_virt(Elf_Phdr *phdr, Elf_Ehdr *ehdr, Elf_Addr base, u_long *vaddr) -{ - int i; - - for (i = 0; i < ehdr->e_phnum; i++) { - switch (phdr[i].p_type) { - case PT_LOAD: - if (phdr[i].p_vaddr > *vaddr) - continue; - if (phdr[i].p_vaddr + phdr[i].p_memsz < *vaddr) - continue; -#ifdef DEBUG1 - printf("input address %lx translated to ", *vaddr); -#endif - *vaddr += phdr[i].p_offset - phdr[i].p_vaddr + base; -#ifdef DEBUG1 - printf("%lx, base %lx %lx %llx\n", *vaddr, base, - phdr[i].p_vaddr, phdr[i].p_offset ); -#endif - break; - default: - break; - } - } -} - -/* - * given a dynamic elf object (executable or binary) - * load any DT_NEEDED entries which were found when - * the object was initially loaded. - */ -int -load_obj_needed(struct elf_object *object) -{ - int i; - Elf_Word *needed_list; - int err; - - needed_list = (Elf_Word *)object->dyn.needed; - for (i = 0; needed_list[i] != 0; i++) { - if (verbose > 1) - printf("lib: %s\n", needed_list[i] + - object->dyn.strtab); - err = load_lib(needed_list[i] + object->dyn.strtab, object); - if (err) { - printf("failed to load lib %s\n", - needed_list[i] + object->dyn.strtab); - return 1; - } - } - return 0; -} - -/* - * allocate a proglist entry for a new binary - * so that it is available for libraries to reference - */ -struct proglist * -elf_newbin(void) -{ - struct proglist *proglist; - proglist = malloc(sizeof (struct proglist)); - if (proglist == NULL) { - printf("unable to allocate proglist\n"); - exit(10); - } - proglist->fixup = NULL; - TAILQ_INIT(&(proglist->curbin_list)); - return proglist; -} - -/* - * Copy the contents of a libraries symbol cache instance into - * the 'global' symbol cache for that library - * this will currently resolve conflicts between mismatched - * libraries by flagging any mismatches as invalid - * which will cause all programs to generate a fixup - * It probably would be interesting to modify this to keep the most - * common entry as a library cache, and only have a fixup in programs - * where the symbol is overridden. - * This is run once each for the (got)symcache and pltsymcache - */ - -struct elf_object badobj_store; -struct elf_object *badobj = &badobj_store; - -/* - * copy the symbols found in a library symcache to the 'master/common' - * symbol table note that this will skip copying the following references - * 1. non-existing entries - * 2. symobj == prog &&& obj != prog - * 3. symobj == prog's interpter (references to dl_open) - */ -void -elf_copy_syms(struct symcache_noflag *tcache, struct symcache_noflag *scache, - struct elf_object *obj, struct elf_object *prog, int nsyms) -{ - int i; - int lib_prog_ref; - for (i = 0; i < nsyms; i++) { - if (scache[i].obj == NULL) - continue; - - if (tcache[i].obj != NULL) { - lib_prog_ref = (obj != prog && scache[i].obj == prog); - if (scache[i].obj != tcache[i].obj || lib_prog_ref) { - if (verbose > 2) { - printf("sym mismatch %d: " - "obj %d: sym %ld %s " - "nobj %s\n", - i, (int)scache[i].obj->dyn.null, - scache[i].sym - - scache[i].obj->dyn.symtab, - scache[i].sym->st_name + - scache[i].obj->dyn.strtab, - scache[i].obj->load_name); - } - - /* - * if one of the symbol entries - * happens to be a self reference - * go ahead and keep that reference - * prevents some instances of fixups - * for every binary, eg one program - * overriding malloc() will not make - * ever binary have a fixup for libc - * references to malloc() - */ - if (scache[i].obj == obj) { - tcache[i].obj = scache[i].obj; - tcache[i].sym = scache[i].sym; - } else if (tcache[i].obj == obj) { - /* no change necessary */ - } else { - tcache[i].obj = badobj; - tcache[i].sym = NULL; - } - } - } else { - if (scache[i].obj != prog) { - tcache[i].obj = scache[i].obj; - tcache[i].sym = scache[i].sym; - } - } - } -} - -void -insert_sym_objcache(struct elf_object *obj, int idx, - const struct elf_object *ref_obj, const Elf_Sym *ref_sym, int flags) -{ - struct symcache_noflag *tcache; - struct elf_object *prog; - - prog = TAILQ_FIRST(&(curbin->curbin_list))->object; - - if (flags) - tcache = objarray[obj->dyn.null].pltsymcache; - else - tcache = objarray[obj->dyn.null].symcache; - - if (tcache[idx].obj != NULL) { - if (ref_obj != tcache[idx].obj || - (obj != prog && ref_obj == prog)) { - if (verbose > 2) { - printf("sym mismatch %d: " - "obj %d: sym %ld %s " - "nobj %s\n", - idx, (int)ref_obj->dyn.null, - ref_sym - - ref_obj->dyn.symtab, - ref_sym->st_name + - ref_obj->dyn.strtab, - ref_obj->load_name); - } - - /* - * if one of the symbol entries - * happens to be a self reference - * go ahead and keep that reference - * prevents some instances of fixups - * for every binary, eg one program - * overriding malloc() will not make - * ever binary have a fixup for libc - * references to malloc() - */ - if (ref_obj == obj) { - tcache[idx].obj = ref_obj; - tcache[idx].sym = ref_sym; - add_fixup_oldprog(prog, obj, idx, ref_obj, - ref_sym, flags); - } else if (tcache[idx].obj == obj) { - /* no change necessary */ - add_fixup_prog(prog, obj, idx, ref_obj, - ref_sym, flags); - } else { - add_fixup_oldprog(prog, obj, idx, - tcache[idx].obj, tcache[idx].sym, flags); - tcache[idx].obj = badobj; - tcache[idx].sym = NULL; - add_fixup_prog(prog, obj, idx, ref_obj, - ref_sym, flags); - } - } - } else { - if (ref_obj != prog) { - tcache[idx].obj = ref_obj; - tcache[idx].sym = ref_sym; - } else { - add_fixup_prog(prog, obj, idx, ref_obj, - ref_sym, flags); - } - } -} - -void -add_fixup_prog(struct elf_object *prog, struct elf_object *obj, int idx, - const struct elf_object *ref_obj, const Elf_Sym *ref_sym, int flag) -{ - struct proglist *pl; - int i, libidx, cnt; - - pl = objarray[prog->dyn.null].proglist; - - libidx = -1; - for (i = 0; i < pl->nobj; i++) { - if (pl->libmap[0][i] == obj->dyn.null) { - libidx = (i * 2) + ((flag & SYM_PLT) ? 1 : 0); - break; - } - } - if (libidx == -1) { - printf("unable to find object\n"); - return; - } - - /* have to check for duplicate patches */ - for (i = 0; i < pl->fixupcnt[libidx]; i++) { - if (pl->fixup[libidx][i].sym == idx) - return; - } - - if (verbose > 1) - printf("fixup for obj %s on prog %s sym %s: %d\n", - obj->load_name, prog->load_name, - ref_obj->dyn.strtab + ref_sym->st_name, - pl->fixupcnt[libidx]); - - if (pl->fixupcntalloc[libidx] < pl->fixupcnt[libidx] + 1) { - pl->fixupcntalloc[libidx] += 16; - pl->fixup[libidx] = reallocarray(pl->fixup[libidx], - pl->fixupcntalloc[libidx], sizeof(struct fixup)); - if (pl->fixup[libidx] == NULL) { - printf("realloc fixup, out of memory\n"); - exit(20); - } - } - cnt = pl->fixupcnt[libidx]; - pl->fixup[libidx][cnt].sym = idx; - pl->fixup[libidx][cnt].obj_idx = ref_obj->dyn.null; - pl->fixup[libidx][cnt].sym_idx = ref_sym - ref_obj->dyn.symtab; - pl->fixupcnt[libidx]++; -} - -void -add_fixup_oldprog(struct elf_object *prog, struct elf_object *obj, int idx, - const struct elf_object *ref_obj, const Elf_Sym *ref_sym, int flag) -{ - struct objlist *ol; - - TAILQ_FOREACH(ol, &(objarray[obj->dyn.null].inst_list), inst_list) { - if (ol->load_prog == prog) { - continue; - } - /* process here */ - - add_fixup_prog(ol->load_prog, obj, idx, ref_obj, ref_sym, flag); - } - -} - -struct elf_object * -elf_lookup_object(const char *name) -{ - struct objlist *ol; - TAILQ_FOREACH(ol, &(curbin->curbin_list), list) { - if (strcmp (name, ol->object->load_name) == 0) { - return ol->object; - } - } - TAILQ_FOREACH(ol, &library_list, list) { - if (strcmp (name, ol->object->load_name) == 0) { - elf_add_object_curbin_list(ol->object); - return ol->object; - } - } - return NULL; -} - -struct elf_object * -elf_lookup_object_devino(dev_t dev, ino_t inode, int objtype) -{ - struct objlist *ol; - TAILQ_FOREACH(ol, &(curbin->curbin_list), list) { - if (ol->object->dev == dev && - ol->object->inode == inode) { - if (ol->object->obj_type != objtype) - return NULL; - return ol->object; - } - } - TAILQ_FOREACH(ol, &library_list, list) { - if (ol->object->dev == dev && - ol->object->inode == inode) { - if (ol->object->obj_type != objtype) - return NULL; - if (objtype != OBJTYPE_EXE) - elf_add_object_curbin_list(ol->object); - return ol->object; - } - } - return NULL; -} - -void -elf_find_symbol_rel(const char *name, struct elf_object *object, - Elf_Rel *rel, struct symcache_noflag *symcache, - struct symcache_noflag *pltsymcache) -{ - struct objlist *ol; - unsigned long h = 0; - const char *p = name; - const Elf_Sym *sym, *ref_sym = NULL; - const Elf_Sym *weak_sym = NULL; - struct elf_object *weak_obj = NULL; - int flags = 0; - int found = 0; - int type, idx; - struct elf_object *ref_object = NULL; - - sym = object->dyn.symtab + ELF_R_SYM(rel->r_info); - - while (*p) { - unsigned long g; - h = (h << 4) + *p++; - if ((g = h & 0xf0000000)) - h ^= g >> 24; - h &= ~g; - } - - type = ELF_R_TYPE(rel->r_info); - flags = SYM_SEARCH_ALL|SYM_WARNNOTFOUND; - if (type == RELOC_JMP_SLOT) - flags |= SYM_PLT; - - TAILQ_FOREACH(ol, &(curbin->curbin_list), list) { - found = elf_find_symbol_obj(ol->object, name, h, flags, &sym, - &weak_sym, &weak_obj); - if (found) { - ref_object = ol->object; - break; - } - - } - if (found) { - ref_object = ol->object; - ref_sym = sym; - } else if (weak_obj != NULL) { - found = 1; - ref_object = weak_obj; - ref_sym = weak_sym; - } - if (found == 1) { - idx = ELF_R_SYM(rel->r_info); - if (flags & SYM_PLT) { - pltsymcache[idx].obj = ref_object; - pltsymcache[idx].sym = ref_sym; - } else { - symcache[idx].obj = ref_object; - symcache[idx].sym = ref_sym; - } - } else { - /* It is not an error to have an undefined weak symbol */ - const Elf_Sym *sym; - sym = object->dyn.symtab + ELF_R_SYM(rel->r_info); - if (ELF_ST_BIND(sym->st_info) != STB_WEAK) { - printf("symbol not found %s\n", name); - } - } -} - -void -elf_find_symbol_rela(const char *name, struct elf_object *object, - Elf_RelA *rela, struct symcache_noflag *symcache, - struct symcache_noflag *pltsymcache) -{ - struct objlist *ol; - unsigned long h = 0; - const char *p = name; - const Elf_Sym *sym, *ref_sym = NULL; - const Elf_Sym *weak_sym = NULL; - struct elf_object *weak_obj = NULL; - int flags = 0; - int found = 0; - int type, idx; - struct elf_object *ref_object = NULL; - - sym = object->dyn.symtab + ELF_R_SYM(rela->r_info); - - while (*p) { - unsigned long g; - h = (h << 4) + *p++; - if ((g = h & 0xf0000000)) - h ^= g >> 24; - h &= ~g; - } - - type = ELF_R_TYPE(rela->r_info); - flags = SYM_SEARCH_ALL|SYM_WARNNOTFOUND; - if (type == RELOC_JMP_SLOT) - flags |= SYM_PLT; - - TAILQ_FOREACH(ol, &(curbin->curbin_list), list) { - -// printf("searching sym [%s] typ %d in obj %s\n", name, type, ol->object->load_name); - found = elf_find_symbol_obj(ol->object, name, h, flags, &sym, - &weak_sym, &weak_obj); - if (found) { - ref_object = ol->object; - break; - } - - } - if (found) { - ref_object = ol->object; - ref_sym = sym; - } else if (weak_obj != NULL) { - found = 1; - ref_object = weak_obj; - ref_sym = weak_sym; - } - if (found == 1) { - idx = ELF_R_SYM(rela->r_info); - if (flags & SYM_PLT) { - pltsymcache[idx].obj = ref_object; - pltsymcache[idx].sym = ref_sym; - } else { - symcache[idx].obj = ref_object; - symcache[idx].sym = ref_sym; - } - } else { - /* It is not an error to have an undefined weak symbol */ - const Elf_Sym *sym; - sym = object->dyn.symtab + ELF_R_SYM(rela->r_info); - if (ELF_ST_BIND(sym->st_info) != STB_WEAK) { - printf("symbol not found %s\n", name); - } - } -} - -int -elf_find_symbol_obj(elf_object_t *object, const char *name, unsigned long hash, - int flags, const Elf_Sym **this, const Elf_Sym **weak_sym, - elf_object_t **weak_object) -{ - const Elf_Sym *symt = object->dyn.symtab; - const char *strt = object->dyn.strtab; - long si; - const char *symn; - - for (si = object->buckets[hash % object->nbuckets]; - si != STN_UNDEF; si = object->chains[si]) { - const Elf_Sym *sym = symt + si; - - if (sym->st_value == 0) - continue; - - if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE && - ELF_ST_TYPE(sym->st_info) != STT_OBJECT && - ELF_ST_TYPE(sym->st_info) != STT_FUNC) - continue; - - symn = strt + sym->st_name; - if (sym != *this && strcmp(symn, name)) - continue; - - /* allow this symbol if we are referring to a function - * which has a value, even if section is UNDEF. - * this allows &func to refer to PLT as per the - * ELF spec. st_value is checked above. - * if flags has SYM_PLT set, we must have actual - * symbol, so this symbol is skipped. - */ - if (sym->st_shndx == SHN_UNDEF) { - if ((flags & SYM_PLT) || sym->st_value == 0 || - ELF_ST_TYPE(sym->st_info) != STT_FUNC) - continue; - } - - if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) { - *this = sym; - return 1; - } else if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { - if (!*weak_sym) { - *weak_sym = sym; - *weak_object = object; - } - } - } - return 0; -} - -void -elf_reloc(struct elf_object *object) -{ - const Elf_Sym *sym; - Elf_Rel *rel; - Elf_RelA *rela; - int numrel; - int numrela; - int i; - struct symcache_noflag *symcache; - struct symcache_noflag *pltsymcache; - - numrel = object->dyn.relsz / sizeof(Elf_Rel); -#ifdef DEBUG1 - printf("rel relocations: %d\n", numrel); -#endif -#if 1 - symcache = calloc(sizeof(struct symcache_noflag), - object->nchains); - pltsymcache = calloc(sizeof(struct symcache_noflag), - object->nchains); - if (symcache == NULL || pltsymcache == NULL) { - printf("unable to allocate memory for cache %s\n", - object->load_name); - exit(20); - } -#endif - rel = object->dyn.rel; - for (i = 0; i < numrel; i++) { - const char *s; - sym = object->dyn.symtab + ELF_R_SYM(rel[i].r_info); - - /* hppa has entries without names, skip them */ - if (sym->st_name == 0) - continue; - - s = (ELF_R_SYM(rel[i].r_info) == 0) ? "<rel>" : - object->dyn.strtab + sym->st_name; -#ifdef DEBUG1 - printf("%d: %x sym %x %s type %d\n", i, rel[i].r_offset, - ELF_R_SYM(rel[i].r_info), s, - ELF_R_TYPE(rel[i].r_info)); -#endif - if (ELF_R_SYM(rel[i].r_info) != 0) { - elf_find_symbol_rel(s, object, &rel[i], - symcache, pltsymcache); - } - } - if (numrel) { - numrel = object->dyn.pltrelsz / sizeof(Elf_Rel); - rel = (Elf_Rel *)(object->Dyn.info[DT_JMPREL]); -#ifdef DEBUG1 - printf("rel plt relocations: %d\n", numrel); -#endif - for (i = 0; i < numrel; i++) { - const char *s; - sym = object->dyn.symtab + ELF_R_SYM(rel[i].r_info); - - /* hppa has entries without names, skip them */ - if (sym->st_name == 0) - continue; - - s = (ELF_R_SYM(rel[i].r_info) == 0) ? "<rel>" : - object->dyn.strtab + sym->st_name; -#ifdef DEBUG1 - printf("%d: %x sym %d %s type %d\n", i, rel[i].r_offset, - ELF_R_SYM(rel[i].r_info), s, - ELF_R_TYPE(rel[i].r_info)); -#endif - if (ELF_R_SYM(rel[i].r_info) != 0) { - elf_find_symbol_rel(s, object, &rel[i], - symcache, pltsymcache); - } - } - } - - numrela = object->dyn.relasz / sizeof(Elf_RelA); -#ifdef DEBUG1 - printf("rela relocations: %d\n", numrela); -#endif - rela = object->dyn.rela; - for (i = 0; i < numrela; i++) { - const char *s; - sym = object->dyn.symtab + ELF_R_SYM(rela[i].r_info); - - /* hppa has entries without names, skip them */ - if (sym->st_name == 0) - continue; - - s = (ELF_R_SYM(rela[i].r_info) == 0) ? "<rel>" : - object->dyn.strtab + sym->st_name; -#ifdef DEBUG1 - printf("%d: %x sym %x %s type %d\n", i, rela[i].r_offset, - ELF_R_SYM(rela[i].r_info), s, - ELF_R_TYPE(rela[i].r_info)); -#endif - if (ELF_R_SYM(rela[i].r_info) != 0) { - elf_find_symbol_rela(s, object, &rela[i], - symcache, pltsymcache); - } - } - if (numrela) { - numrela = object->dyn.pltrelsz / sizeof(Elf_RelA); -#ifdef DEBUG1 - printf("rela plt relocations: %d\n", numrela); -#endif - rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]); - - for (i = 0; i < numrela; i++) { - const char *s; - sym = object->dyn.symtab + ELF_R_SYM(rela[i].r_info); - - /* hppa has entries without names, skip them */ - if (sym->st_name == 0) - continue; - - s = (ELF_R_SYM(rela[i].r_info) == 0) ? "<rel>" : - object->dyn.strtab + sym->st_name; -#ifdef DEBUG1 - printf("%d: %x sym %x %s type %d\n", i, - rela[i].r_offset, - ELF_R_SYM(rela[i].r_info), s, - ELF_R_TYPE(rela[i].r_info)); -#endif - if (ELF_R_SYM(rela[i].r_info) != 0) { - elf_find_symbol_rela(s, object, &rela[i], - symcache, pltsymcache); - } - } - } - - for (i = 0; i < object->nchains; i++) - if (symcache[i].sym != NULL) - insert_sym_objcache(object, i, symcache[i].obj, - symcache[i].sym, 0); - - for (i = 0; i < object->nchains; i++) - if (pltsymcache[i].sym != NULL) - insert_sym_objcache(object, i, pltsymcache[i].obj, - pltsymcache[i].sym, SYM_PLT); - - free(symcache); - free(pltsymcache); -} - -void -elf_resolve_curbin(void) -{ - struct objlist *ol; - int numobj = 0; - -#ifdef DEBUG1 - elf_print_curbin_list(curbin); -#endif - TAILQ_FOREACH(ol, &(curbin->curbin_list), list) { - numobj++; - } - curbin->nobj = numobj; - curbin->libmap = xcalloc(numobj, sizeof (u_int32_t *)); - curbin->libmap[0] = xcalloc(numobj, sizeof (u_int32_t *)); - curbin->fixup = xcalloc(2 * numobj, sizeof (struct fixup *)); - curbin->fixupcnt = xcalloc(2 * numobj, sizeof (int)); - curbin->fixupcntalloc = xcalloc(2 * numobj, sizeof (int)); - - numobj = 0; - TAILQ_FOREACH(ol, &(curbin->curbin_list), list) { - curbin->libmap[0][numobj] = ol->object->dyn.null; - numobj++; - } - TAILQ_FOREACH(ol, &(curbin->curbin_list), list) { - elf_reloc(ol->object); - } -} - -void -elf_add_object_curbin_list(struct elf_object *object) -{ - struct objlist *ol; - - ol = xmalloc(sizeof (struct objlist)); - ol->object = object; - TAILQ_INSERT_TAIL(&(curbin->curbin_list), ol, list); - if (load_object == NULL) - load_object = object; - ol->load_prog = load_object; - - TAILQ_INSERT_TAIL(&(objarray[object->dyn.null].inst_list), ol, - inst_list); -} -void -elf_init_objarray(void) -{ - objarray_sz = 512; - objarray = xcalloc(sizeof (objarray[0]), objarray_sz); -} - -void -elf_sum_reloc(void) -{ - int numobjs; - int err = 0; - struct objlist *ol; - struct proglist *pl; - - TAILQ_FOREACH(ol, &library_list, list) { - err += elf_prep_lib_prebind(ol->object); - } - TAILQ_FOREACH(pl, &prog_list, list) { - numobjs = 0; - TAILQ_FOREACH(ol, &(pl->curbin_list), list) { - numobjs++; - } - pl->nobj = numobjs; - } - - TAILQ_FOREACH(pl, &prog_list, list) - err += elf_prep_bin_prebind(pl); - - if (err != 0) - printf("failures %d\n", err); -} - -int -elf_prep_lib_prebind(struct elf_object *object) -{ - int numlibs = 0; - int ret = 0; - int i; - int ref_obj; - int *libmap; - int *idxtolib; - struct nameidx *nameidx; - char *nametab; - int nametablen; - struct symcache_noflag *symcache; - struct symcache_noflag *pltsymcache; - struct symcachetab *symcachetab; - int symcache_cnt = 0; - struct symcachetab *pltsymcachetab; - int pltsymcache_cnt = 0; - - symcache = objarray[object->dyn.null].symcache; - pltsymcache = objarray[object->dyn.null].pltsymcache; - libmap = xcalloc(objarray_cnt, sizeof (int)); - idxtolib = xcalloc(objarray_cnt, sizeof (int)); - objarray[object->dyn.null].idxtolib = idxtolib; - - for (i = 0; i < objarray_cnt; i++) - libmap[i] = -1; - - nametablen = 0; - for (i = 0; i < object->nchains; i++) { - if (symcache[i].sym == NULL) - continue; - ref_obj = symcache[i].obj->dyn.null; - symcache_cnt++; - if (libmap[ref_obj] != -1) - continue; - libmap[ref_obj] = numlibs; - idxtolib[numlibs] = ref_obj; - nametablen += strlen(symcache[i].obj->load_name) + 1; - numlibs++; - } - symcachetab = xcalloc(symcache_cnt , sizeof(struct symcachetab)); - - symcache_cnt = 0; - for (i = 0; i < object->nchains; i++) { - if (symcache[i].sym == NULL) - continue; - symcachetab[symcache_cnt].idx = i; - symcachetab[symcache_cnt].obj_idx = - libmap[symcache[i].obj->dyn.null]; - symcachetab[symcache_cnt].sym_idx = - symcache[i].sym - symcache[i].obj->dyn.symtab; - symcache_cnt++; - } - for (i = 0; i < object->nchains; i++) { - if (pltsymcache[i].sym == NULL) - continue; - ref_obj = pltsymcache[i].obj->dyn.null; - pltsymcache_cnt++; - if (libmap[ref_obj] != -1) - continue; - libmap[ref_obj] = numlibs; - idxtolib[numlibs] = ref_obj; - nametablen += strlen(pltsymcache[i].obj->load_name) + 1; - numlibs++; - } - pltsymcachetab = xcalloc(pltsymcache_cnt , sizeof(struct symcachetab)); - - pltsymcache_cnt = 0; - for (i = 0; i < object->nchains; i++) { - if (pltsymcache[i].sym == NULL) - continue; - pltsymcachetab[pltsymcache_cnt].idx = i; - pltsymcachetab[pltsymcache_cnt].obj_idx = - libmap[pltsymcache[i].obj->dyn.null]; - pltsymcachetab[pltsymcache_cnt].sym_idx = - pltsymcache[i].sym - pltsymcache[i].obj->dyn.symtab; - pltsymcache_cnt++; - } - - objarray[object->dyn.null].numlibs = numlibs; - - nameidx = xcalloc(numlibs, sizeof (struct nameidx)); - nametab = xmalloc(nametablen); - - nametablen = 0; - for (i = 0; i < numlibs; i++) { - nameidx[i].name = nametablen; - nameidx[i].id0 = objarray[idxtolib[i]].id0; - nameidx[i].id1 = objarray[idxtolib[i]].id1; - nametablen += strlen(objarray[idxtolib[i]].obj->load_name) + 1; - strlcpy(&nametab[nameidx[i].name], - objarray[idxtolib[i]].obj->load_name, - nametablen - nameidx[i].name); - } - - /* skip writing lib if using old prebind data */ - if (objarray[object->dyn.null].oprebind_data == NULL) - ret = elf_write_lib(object, nameidx, nametab, nametablen, - numlibs, 0, NULL, NULL, NULL, NULL, symcachetab, - symcache_cnt, pltsymcachetab, pltsymcache_cnt); - - free(nameidx); - free(nametab); - free(libmap); - free(pltsymcachetab); - free(symcachetab); - - return ret; -} - -int -elf_prep_bin_prebind(struct proglist *pl) -{ - int ret; - int numlibs = 0; - int i, j; - int ref_obj; - int *libmap; - int *idxtolib; - struct nameidx *nameidx; - char *nametab; - int nametablen; - struct symcache_noflag *symcache; - struct symcache_noflag *pltsymcache; - struct symcachetab *symcachetab; - int symcache_cnt; - struct symcachetab *pltsymcachetab; - int pltsymcache_cnt; - struct elf_object *object; - struct objlist *ol; - - object = TAILQ_FIRST(&(pl->curbin_list))->object; - symcache = objarray[object->dyn.null].symcache; - pltsymcache = objarray[object->dyn.null].pltsymcache; - libmap = xcalloc(objarray_cnt, sizeof (int)); - idxtolib = xcalloc(pl->nobj, sizeof (int)); - - for (i = 0; i < objarray_cnt; i++) - libmap[i] = -1; - - for (i = 0; i < pl->nobj; i++) - idxtolib[i] = -1; - - nametablen = 0; - TAILQ_FOREACH(ol, &(pl->curbin_list), list) { - ref_obj = ol->object->dyn.null; - nametablen += strlen(ol->object->load_name) + 1; - libmap[ref_obj] = numlibs; - idxtolib[numlibs] = ref_obj; - numlibs++; - } - - /* do got */ - symcache_cnt = 0; - for (i = 0; i < object->nchains; i++) { - if (symcache[i].sym != NULL) - symcache_cnt++; - } - - symcachetab = xcalloc(symcache_cnt , sizeof(struct symcachetab)); - - symcache_cnt = 0; - for (i = 0; i < object->nchains; i++) { - if (symcache[i].sym == NULL) - continue; - symcachetab[symcache_cnt].idx = i; - symcachetab[symcache_cnt].obj_idx = - libmap[symcache[i].obj->dyn.null]; - symcachetab[symcache_cnt].sym_idx = - symcache[i].sym - symcache[i].obj->dyn.symtab; - symcache_cnt++; - } - - /* now do plt */ - pltsymcache_cnt = 0; - for (i = 0; i < object->nchains; i++) { - if (pltsymcache[i].sym != NULL) - pltsymcache_cnt++; - } - pltsymcachetab = xcalloc(pltsymcache_cnt , sizeof(struct symcachetab)); - - pltsymcache_cnt = 0; - for (i = 0; i < object->nchains; i++) { - if (pltsymcache[i].sym == NULL) - continue; - pltsymcachetab[pltsymcache_cnt].idx = i; - pltsymcachetab[pltsymcache_cnt].obj_idx = - libmap[pltsymcache[i].obj->dyn.null]; - pltsymcachetab[pltsymcache_cnt].sym_idx = - pltsymcache[i].sym - pltsymcache[i].obj->dyn.symtab; - pltsymcache_cnt++; - } - - objarray[object->dyn.null].numlibs = numlibs; - - nameidx = xcalloc(numlibs, sizeof (struct nameidx)); - nametab = xmalloc(nametablen); - - nametablen = 0; - for (i = 0; i < numlibs; i++) { - nameidx[i].name = nametablen; - nameidx[i].id0 = objarray[idxtolib[i]].id0; - nameidx[i].id1 = objarray[idxtolib[i]].id1; - nametablen += strlen(objarray[idxtolib[i]].obj->load_name) + 1; - - strlcpy(&nametab[nameidx[i].name], - objarray[idxtolib[i]].obj->load_name, - nametablen - nameidx[i].name); - } - pl->libmapcnt = xcalloc(numlibs, sizeof(u_int32_t)); - - /* have to do both got and plt fixups */ - for (i = 0; i < numlibs; i++) { - for (j = 0; j < pl->fixupcnt[2*i]; j++) { - pl->fixup[2*i][j].obj_idx = - libmap[pl->fixup[2*i][j].obj_idx]; - } - for (j = 0; j < pl->fixupcnt[2*i+1]; j++) { - pl->fixup[2*i+1][j].obj_idx = - libmap[pl->fixup[2*i+1][j].obj_idx]; - } - - pl->libmapcnt[i] = objarray[idxtolib[i]].numlibs; - pl->libmap[i] = xcalloc(objarray[idxtolib[i]].numlibs, - sizeof(u_int32_t)); - if (i != 0) { - for (j = 0; j < objarray[idxtolib[i]].numlibs; j++) { - pl->libmap[i][j] = - libmap[objarray[idxtolib[i]].idxtolib[j]]; - } - } - } - - ret = elf_write_lib(object, nameidx, nametab, nametablen, numlibs, - numlibs, pl->fixup, pl->fixupcnt, - pl->libmap, pl->libmapcnt, - symcachetab, symcache_cnt, - pltsymcachetab, pltsymcache_cnt); - - free(symcachetab); - free(pltsymcachetab); - free(idxtolib); - free(nameidx); - free(nametab); - free(libmap); - - return ret; -} - - -int -elf_write_lib(struct elf_object *object, struct nameidx *nameidx, - char *nametab, int nametablen, int numlibs, - int nfixup, struct fixup **fixup, int *fixupcnt, - u_int32_t **libmap, int *libmapcnt, - struct symcachetab *symcachetab, int symcache_cnt, - struct symcachetab *pltsymcachetab, int pltsymcache_cnt) -{ - struct prebind_footer footer; - struct prebind_info info; - u_int32_t footer_offset, *maptab = NULL; - u_int32_t next_start, *fixuptab = NULL; - struct stat ifstat; - off_t base_offset; - ssize_t len; - int fd = -1, i; - int readonly = 0; - - /* open the file, if in safe mode, only open it readonly */ - if (safe == 0) - fd = open(object->load_name, O_RDWR); - if (fd == -1) { - if (safe != 0 || errno == ETXTBSY) - fd = open(object->load_name, O_RDONLY); - if (fd == -1) { - perror(object->load_name); - return 1; - } - readonly = 1; - } - if (lseek(fd, -((off_t)sizeof(struct prebind_footer)), SEEK_END) - == -1) { - perror(object->load_name); - close(fd); - return 1; - } - - len = read(fd, &footer, sizeof(struct prebind_footer)); - if (len != sizeof(struct prebind_footer)) { - close(fd); - if (len == -1) - perror(object->load_name); - else - /* paranoia */ - warnx("%s on %s: short read (corrupted file?)", - __func__, object->load_name); - return 1; - } - - if (fstat(fd, &ifstat) == -1) { - perror(object->load_name); - exit(10); - } - - if (footer.bind_id[0] == BIND_ID0 && - footer.bind_id[1] == BIND_ID1 && - footer.bind_id[2] == BIND_ID2 && - footer.bind_id[3] == BIND_ID3 && - readonly == 0) { - - ftruncate(fd, footer.orig_size); - elf_clear_prog_load(fd, object); - - base_offset = footer.orig_size; - } else { - base_offset = ifstat.st_size; - } - - bzero(&footer, sizeof(struct prebind_footer)); - - - /* verify dev/inode - do we care about last modified? */ - - /* pieces to store on lib - * - * offset to footer - * nameidx - numlibs * sizeof nameidx - * symcache - symcache_cnt * sizeof (symcache_idx) - * pltsymcache - pltsymcache_cnt * sizeof (symcache_idx) - * fixup(N/A for lib) - nfixup * sizeof (symcache_idx) - * nametab - nametablen - * footer (not aligned) - */ - - footer.orig_size = base_offset; - base_offset = ELF_ROUND(base_offset, sizeof(u_int64_t)); - footer.prebind_base = base_offset; - footer.nameidx_idx = sizeof(u_int32_t); - footer.symcache_idx = footer.nameidx_idx + - numlibs * sizeof (struct nameidx); - footer.pltsymcache_idx = footer.symcache_idx + - symcache_cnt * sizeof (struct nameidx); - footer.symcache_cnt = symcache_cnt; - footer.pltsymcache_cnt = pltsymcache_cnt; - footer.fixup_cnt = 0; - footer.numlibs = numlibs; - next_start = footer.pltsymcache_idx + - (pltsymcache_cnt * sizeof (struct symcachetab)); - if (nfixup != 0) { - footer.fixup_cnt = nfixup; - footer.fixup_idx = next_start; - next_start += 2*nfixup * sizeof(u_int32_t); - footer.fixupcnt_idx = next_start; - next_start += 2*nfixup * sizeof(u_int32_t); - fixuptab = xcalloc(2*nfixup, sizeof(u_int32_t)); - for (i = 0; i < 2*nfixup; i++) { - fixuptab[i] = next_start; - next_start += fixupcnt[i] * sizeof(struct fixup); - } - footer.libmap_idx = next_start; - next_start += 2*nfixup * sizeof(u_int32_t); - maptab = xcalloc(2*nfixup, sizeof(u_int32_t)); - maptab[0] = next_start; - for (i = 1; i < nfixup; i++) { - maptab[i] = next_start; - next_start += libmapcnt[i] * sizeof(u_int32_t); - } - } - - footer.nametab_idx = next_start; - next_start += nametablen; - next_start = ELF_ROUND(next_start, sizeof(u_int64_t)); - footer_offset = next_start; - if (verbose > 1) { - printf("footer_offset %d\n", footer_offset); - } - footer.prebind_size = next_start + sizeof(struct prebind_footer); - - footer.prebind_version = PREBIND_VERSION; - footer.id0 = objarray[object->dyn.null].id0; - footer.id1 = objarray[object->dyn.null].id1; - footer.bind_id[0] = BIND_ID0; - footer.bind_id[1] = BIND_ID1; - footer.bind_id[2] = BIND_ID2; - footer.bind_id[3] = BIND_ID3; - - - info.object = object; - info.footer = &footer; - info.footer_offset = footer_offset; - info.nameidx = nameidx; - info.symcache = symcachetab; - - - info.pltsymcache = pltsymcachetab; - info.nfixup = nfixup; - if (nfixup != 0) { - info.fixuptab = fixuptab; - info.fixupcnt = fixupcnt; - info.fixup = fixup; - info.maptab = maptab; - info.libmap = libmap; - info.libmapcnt = libmapcnt; - } - - info.nametab = nametab; - info.nametablen = nametablen; - - - if (readonly) { - prebind_writenewfile(fd, object->load_name, &ifstat, - (off_t)footer.orig_size, &info); - } else { - prebind_writefile(fd, &info); - } - - if (fstat(fd, &ifstat) == -1) { - perror(object->load_name); - exit(10); - } - if (nfixup != 0) { - free(fixuptab); - free(maptab); - } - - if (verbose > 0) - printf("%s: prebind info %d bytes old size %lld, growth %f\n", - object->load_name, footer.prebind_size, footer.orig_size, - (double)(footer.prebind_size) / footer.orig_size); - - if (verbose > 1) - elf_dump_footer(&footer); - - close(fd); - return 0; -} - -int -prebind_writefile(int fd, struct prebind_info *info) -{ - int i; - - struct prebind_footer *footer = info->footer; - - lseek(fd, footer->prebind_base, SEEK_SET); - write(fd, &info->footer_offset, sizeof(u_int32_t)); - - lseek(fd, footer->prebind_base+footer->nameidx_idx, SEEK_SET); - write(fd, info->nameidx, footer->numlibs * sizeof (struct nameidx)); - - lseek(fd, footer->prebind_base+footer->symcache_idx, SEEK_SET); - write(fd, info->symcache, footer->symcache_cnt * - sizeof (struct symcachetab)); - - lseek(fd, footer->prebind_base+footer->pltsymcache_idx, SEEK_SET); - write(fd, info->pltsymcache, footer->pltsymcache_cnt * - sizeof (struct symcachetab)); - - if (info->nfixup != 0) { - lseek(fd, footer->prebind_base+footer->fixup_idx, SEEK_SET); - write(fd, info->fixuptab, 2*info->nfixup * sizeof(u_int32_t)); - lseek(fd, footer->prebind_base+footer->fixupcnt_idx, SEEK_SET); - write(fd, info->fixupcnt, 2*info->nfixup * sizeof(u_int32_t)); - for (i = 0; i < 2*info->nfixup; i++) { - lseek(fd, footer->prebind_base+info->fixuptab[i], - SEEK_SET); - write(fd, info->fixup[i], info->fixupcnt[i] * - sizeof(struct fixup)); - } - - lseek(fd, footer->prebind_base+footer->libmap_idx, SEEK_SET); - write(fd, info->maptab, info->nfixup * sizeof(u_int32_t)); - for (i = 0; i < info->nfixup; i++) { - lseek(fd, footer->prebind_base+info->maptab[i], - SEEK_SET); - write(fd, info->libmap[i], info->libmapcnt[i] * - sizeof(u_int32_t)); - } - } - lseek(fd, footer->prebind_base+footer->nametab_idx, SEEK_SET); - write(fd, info->nametab, info->nametablen); - - lseek(fd, footer->prebind_base+info->footer_offset, SEEK_SET); - write(fd, footer, sizeof (struct prebind_footer)); - - if (info->object->obj_type == OBJTYPE_EXE) - elf_fixup_prog_load(fd, info->footer, info->object); - - return 0; -} - -int -prebind_writenewfile(int infd, char *name, struct stat *st, off_t orig_size, - struct prebind_info *info) -{ - struct timespec ts[2]; - char *newname, *buf; - ssize_t len, wlen; - int outfd; - - if (asprintf(&newname, "%s.XXXXXXXXXX", name) == -1) { - if (verbose) - warn("asprintf"); - return (-1); - } - outfd = open(newname, O_CREAT|O_RDWR|O_TRUNC, 0600); - if (outfd == -1) { - warn("%s", newname); - free(newname); - return (-1); - } - - buf = malloc(BUFSZ); - if (buf == NULL) { - if (verbose) - warn("malloc"); - goto fail; - } - - /* copy old file to new file */ - lseek(infd, (off_t)0, SEEK_SET); - while (1) { - len = read(infd, buf, BUFSIZ); - if (len == -1) { - if (verbose) - warn("read"); - free(buf); - goto fail; - } - if (len == 0) - break; - wlen = write(outfd, buf, len); - if (wlen != len) { - free(buf); - goto fail; - } - } - free(buf); - - /* now back track, and delete the header */ - if (prebind_remove_load_section(outfd, newname) == -1) - goto fail; - if (orig_size != (off_t)-1 && - ftruncate(outfd, orig_size) == -1) - goto fail; - - prebind_writefile(outfd, info); - - /* move new file into place */ - ts[0] = st->st_atimespec; - ts[1] = st->st_mtimespec; - if (futimens(outfd, ts) == -1) - goto fail; - if (fchown(outfd, st->st_uid, st->st_gid) == -1) - goto fail; - if (fchmod(outfd, st->st_mode) == -1) - goto fail; - if (fchflags(outfd, st->st_flags) == -1) - goto fail; - if (fstat(outfd, st) == -1) { - /* XXX */ - goto fail; - } - if (rename(newname, name) == -1) - goto fail; - - close (outfd); - return (0); - -fail: - unlink(newname); - free(newname); - close(outfd); - return (-1); -} - -void -elf_fixup_prog_load(int fd, struct prebind_footer *footer, - struct elf_object *object) -{ - void *buf; - Elf_Ehdr *ehdr; - Elf_Phdr *phdr; - Elf_Phdr phdr_empty; - int loadsection; - - buf = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_FILE | MAP_SHARED, - fd, 0); - if (buf == MAP_FAILED) { - printf("%s: cannot mmap for write\n", object->load_name); - return; - } - - ehdr = (Elf_Ehdr *) buf; - phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff); - - for (loadsection = 0; loadsection < ehdr->e_phnum; loadsection++) { - if (phdr[loadsection].p_type == PT_LOAD) - break; - } - - /* verify that extra slot is empty */ - bzero(&phdr_empty, sizeof(phdr_empty)); - if (bcmp(&phdr[ehdr->e_phnum], &phdr_empty, sizeof(phdr_empty)) != 0) { - printf("extra slot not empty\n"); - goto done; - } - phdr[ehdr->e_phnum].p_type = PT_LOAD; - phdr[ehdr->e_phnum].p_flags = PF_R | 0x08000000; - phdr[ehdr->e_phnum].p_offset = footer->prebind_base; - phdr[ehdr->e_phnum].p_vaddr = footer->prebind_base | 0x80000000; - phdr[ehdr->e_phnum].p_paddr = footer->prebind_base | 0x40000000; - phdr[ehdr->e_phnum].p_filesz = footer->prebind_size; - phdr[ehdr->e_phnum].p_memsz = footer->prebind_size; - phdr[ehdr->e_phnum].p_align = phdr[loadsection].p_align; - ehdr->e_phnum++; - -done: - msync(buf, 8192, MS_SYNC); - munmap(buf, 8192); -} - -void -elf_clear_prog_load(int fd, struct elf_object *object) -{ - void *buf; - Elf_Ehdr *ehdr; - Elf_Phdr *phdr; - Elf_Phdr phdr_empty; - int loadsection; - - buf = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_FILE | MAP_SHARED, - fd, 0); - if (buf == MAP_FAILED) { - printf("%s: cannot mmap for write\n", object->load_name); - return; - } - - ehdr = (Elf_Ehdr *) buf; - phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff); - - if (ehdr->e_type != ET_EXEC) { - goto done; - } - - loadsection = ehdr->e_phnum - 1; - if ((phdr[loadsection].p_type != PT_LOAD) || - ((phdr[loadsection].p_flags & 0x08000000) == 0)) { - /* doesn't look like ours */ - printf("mapped, %s id doesn't match %lx %d %d\n", - object->load_name, - (long)(phdr[loadsection].p_vaddr), - phdr[loadsection].p_flags, loadsection); - goto done; - } - - /* verify that extra slot is empty */ - bzero(&phdr[loadsection], sizeof(phdr_empty)); - - ehdr->e_phnum--; - -done: - msync(buf, 8192, MS_SYNC); - munmap(buf, 8192); -} - -void -elf_add_object(struct elf_object *object, int objtype) -{ - struct objarray_list *newarray; - struct objlist *ol; - ol = xmalloc(sizeof (struct objlist)); - ol->object = object; - if (objtype != OBJTYPE_EXE) - TAILQ_INSERT_TAIL(&library_list, ol, list); - if (objarray_cnt+1 >= objarray_sz) { - objarray_sz += 512; - newarray = reallocarray(objarray, objarray_sz, - sizeof(objarray[0])); - if (newarray != NULL) - objarray = newarray; - else { - perror("objarray"); - exit(20); - } - } - object->dyn.null = objarray_cnt; /* Major abuse, I know */ - TAILQ_INIT(&(objarray[objarray_cnt].inst_list)); - objarray[objarray_cnt].obj = object; - objarray[objarray_cnt].id0 = arc4random(); - objarray[objarray_cnt].id1 = arc4random(); - - objarray[objarray_cnt].symcache = xcalloc( - sizeof(struct symcache_noflag), object->nchains); - objarray[objarray_cnt].pltsymcache = xcalloc( - sizeof(struct symcache_noflag), object->nchains); - - objarray[objarray_cnt].oprebind_data = NULL; - objarray[objarray_cnt].proglist = NULL; - objarray[objarray_cnt].numlibs = 0; - objarray_cnt++; - - elf_add_object_curbin_list(object); -} - -void -elf_free_curbin_list(elf_object_t *object) -{ - struct objlist *ol; - int i; - - while (!TAILQ_EMPTY(&(curbin->curbin_list))) { - ol = TAILQ_FIRST(&(curbin->curbin_list)); - TAILQ_REMOVE(&(objarray[ol->object->dyn.null].inst_list), ol, inst_list); - TAILQ_REMOVE(&(curbin->curbin_list), ol, list); - free(ol); - } - - printf("trying to remove %s\n", object->load_name); - for (i = objarray_cnt; i != 0;) { - i--; - printf("obj %s\n", objarray[i].obj->load_name); - if (objarray[i].obj == object) { - printf("found obj at %d max obj %d\n", i, objarray_cnt); - TAILQ_FOREACH(ol, &(curbin->curbin_list), list) { - } - /* XXX - delete references */ - objarray_cnt = i; - break; - } - } -} - -void -elf_print_objarray(void) -{ - int i; - struct objlist *ol; - - printf("loaded objs # %d\n", objarray_cnt); - for (i = 0; i < objarray_cnt; i++) { - printf("%3d: %d obj %s\n", i, (int)objarray[i].obj->dyn.null, - objarray[i].obj->load_name); - TAILQ_FOREACH(ol, &(objarray[i].inst_list), - inst_list) { - printf("\tprog %s\n", ol->load_prog->load_name); - } - } -} - -void -elf_load_existing_prebind(struct elf_object *object, int fd) -{ - struct prebind_footer footer; - void *prebind_data; - ssize_t len; - - lseek(fd, -((off_t)sizeof(struct prebind_footer)), SEEK_END); - len = read(fd, &footer, sizeof(struct prebind_footer)); - if (len != sizeof(struct prebind_footer)) - return; - - if (footer.bind_id[0] != BIND_ID0 || - footer.bind_id[1] != BIND_ID1 || - footer.bind_id[2] != BIND_ID2 || - footer.bind_id[3] != BIND_ID3) - return; - - prebind_data = mmap(0, footer.prebind_size, PROT_READ, - MAP_FILE, fd, footer.prebind_base); - if (prebind_data == MAP_FAILED) - return; - objarray[object->dyn.null].oprebind_data = prebind_data; - objarray[object->dyn.null].id0 = footer.id0; - objarray[object->dyn.null].id1 = footer.id1; - - copy_oldsymcache(object->dyn.null, prebind_data); -} - -void -copy_oldsymcache(int objidx, char *prebind_map) -{ - struct prebind_footer *footer; - struct elf_object *tobj; - struct symcache_noflag *tcache; - struct symcachetab *symcache; - int i, j, found, *idxtolib; - char *c, *nametab; - u_int32_t offset; - u_int32_t *poffset; - struct nameidx *nameidx; - - poffset = (u_int32_t *)prebind_map; - c = prebind_map; - offset = *poffset; - c += offset; - footer = (void *)c; - - nameidx = (void *)(prebind_map + footer->nameidx_idx); - nametab = (void *)(prebind_map + footer->nametab_idx); - - idxtolib = xcalloc(footer->numlibs, sizeof(int)); - found = 0; - for (i = 0; i < footer->numlibs; i++) { - found = 0; - for (j = 0; j < objarray_cnt; j++) { - if (objarray[j].id0 == nameidx[i].id0 && - objarray[j].id1 == nameidx[i].id1) { - found = 1; - idxtolib[i] = j; - if (strcmp(objarray[j].obj->load_name, - &nametab[nameidx[i].name]) != 0) { - printf("warning filename mismatch" - " [%s] [%s]\n", - objarray[j].obj->load_name, - &nametab[nameidx[i].name]); - } - } - } - if (found == 0) - break; - } - if (found == 0) - goto done; - - /* build idxtolibs */ - tcache = objarray[objidx].symcache; - symcache = (void *)(prebind_map + footer->symcache_idx); - - for (i = 0; i < footer->symcache_cnt; i++) { - tobj = objarray[idxtolib[symcache[i].obj_idx]].obj; - - tcache[symcache[i].idx].obj = tobj; - tcache[symcache[i].idx].sym = tobj->dyn.symtab + - symcache[i].sym_idx; - } - - tcache = objarray[objidx].pltsymcache; - symcache = (void *)(prebind_map + footer->pltsymcache_idx); - for (i = 0; i < footer->pltsymcache_cnt; i++) { - tobj = objarray[idxtolib[symcache[i].obj_idx]].obj; - - tcache[symcache[i].idx].obj = tobj; - tcache[symcache[i].idx].sym = tobj->dyn.symtab + - symcache[i].sym_idx; - } -done: - free(idxtolib); - /* munmap(prebind_map, size);*/ -} diff --git a/libexec/ld.so/ldconfig/prebind.h b/libexec/ld.so/ldconfig/prebind.h deleted file mode 100644 index c9e3c345342..00000000000 --- a/libexec/ld.so/ldconfig/prebind.h +++ /dev/null @@ -1,68 +0,0 @@ -/* $OpenBSD: prebind.h,v 1.2 2006/06/26 23:26:12 drahn Exp $ */ -/* - * Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define PREBIND_VERSION 2 -struct prebind_footer { - off_t prebind_base; - u_int32_t nameidx_idx; - u_int32_t symcache_idx; - u_int32_t pltsymcache_idx; - u_int32_t fixup_idx; - u_int32_t nametab_idx; - u_int32_t fixupcnt_idx; - u_int32_t libmap_idx; - - u_int32_t symcache_cnt; - u_int32_t pltsymcache_cnt; - u_int32_t fixup_cnt; - u_int32_t numlibs; - u_int32_t prebind_size; - - u_int32_t id0; - u_int32_t id1; - /* do not modify or add fields below this point in the struct */ - off_t orig_size; - u_int32_t prebind_version; - char bind_id[4]; -#define BIND_ID0 'P' -#define BIND_ID1 'R' -#define BIND_ID2 'E' -#define BIND_ID3 'B' -}; - - -struct nameidx { - u_int32_t name; - u_int32_t id0; - u_int32_t id1; -}; - -struct symcachetab { - u_int32_t idx; - u_int32_t obj_idx; - u_int32_t sym_idx; -}; - -struct fixup { - u_int32_t sym; - u_int32_t obj_idx; - u_int32_t sym_idx; -}; - -int prebind_delete(char **argv); -int prebind(char **argv); -int prebind_remove_load_section(int fd, char *name); diff --git a/libexec/ld.so/ldconfig/prebind_delete.c b/libexec/ld.so/ldconfig/prebind_delete.c deleted file mode 100644 index abd55371a29..00000000000 --- a/libexec/ld.so/ldconfig/prebind_delete.c +++ /dev/null @@ -1,301 +0,0 @@ -/* $OpenBSD: prebind_delete.c,v 1.14 2015/12/17 18:37:58 mmcc Exp $ */ - -/* - * Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/exec_elf.h> -#include <elf_abi.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <dirent.h> -#include <err.h> -#include <errno.h> -#include "prebind.h" - -#define BUFSZ (256 * 1024) - -int strip_prebind(char *file); -int prebind_remove_load_section(int fd, char *name); -int prebind_newfile(int fd, char *name, struct stat *st, off_t orig_size); -int strip_file_or_dir(char *name); -int strip_dir(char *dir); - -extern int verbose; - -int -prebind_delete(char **argv) -{ - while (*argv) { - if (strip_file_or_dir(*argv) == -1) - return (1); - argv++; - } - return (0); -} - -int -strip_file_or_dir(char *name) -{ - struct stat sb; - int ret = -1; - - ret = lstat(name, &sb); - if (ret != 0) - return 0; - switch (sb.st_mode & S_IFMT) { - case S_IFREG: - ret = strip_prebind(name); - break; - case S_IFDIR: - if (verbose > 0) - printf("loading dir %s\n", name); - ret = strip_dir(name); - break; - default: - ; /* links and other files we skip */ - ret = 0; - } - return ret; -} - -int -strip_dir(char *dir) -{ - struct dirent *dp; - struct stat sb; - DIR *dirp; - char *buf; - int ret; - - dirp = opendir(dir); - - /* if dir failed to open, skip */ - if (dirp == NULL) - return 0; - - ret = 0; - while ((dp = readdir(dirp)) != NULL && ret != -1) { - ret = -1; - switch (dp->d_type) { - case DT_UNKNOWN: - /* - * NFS will return unknown, since load_file - * does stat the file, this just - */ - if (asprintf(&buf, "%s/%s", dir, dp->d_name) == -1) { - if (verbose) - warn("asprintf"); - goto done; - } - lstat(buf, &sb); - if (sb.st_mode == S_IFREG) - ret = strip_prebind(buf); - free(buf); - break; - case DT_REG: - if (asprintf(&buf, "%s/%s", dir, dp->d_name) == -1) { - if (verbose) - warn("asprintf"); - goto done; - } - ret = strip_prebind(buf); - free(buf); - break; - default: - /* other files symlinks, dirs, ... we ignore */ - ret = 0; - ; - } - } -done: - closedir(dirp); - return ret; -} - -int -strip_prebind(char *file) -{ - struct prebind_footer footer; - extern char *__progname; - int fd, rdonly = 0; - struct stat st; - ssize_t bytes; - - fd = open(file, O_RDWR); - if (fd == -1 && errno == ETXTBSY) { - fd = open(file, O_RDONLY); - rdonly = 1; - } - if (fd == -1) { - warn("%s", file); - return (-1); - } - - if (fstat(fd, &st) == -1) - return (-1); - - lseek(fd, -((off_t)sizeof(struct prebind_footer)), SEEK_END); - bytes = read(fd, &footer, sizeof(struct prebind_footer)); - if (bytes != sizeof(struct prebind_footer)) - goto done; - - if (footer.bind_id[0] != BIND_ID0 || footer.bind_id[1] != BIND_ID1 || - footer.bind_id[2] != BIND_ID2 || footer.bind_id[3] != BIND_ID3) { - if (verbose) - fprintf(stderr, "%s: no prebind header\n", file); - goto done; - } - - if (rdonly) { - fd = prebind_newfile(fd, file, &st, footer.orig_size); - } else { - prebind_remove_load_section(fd, file); - ftruncate(fd, footer.orig_size); - } - - if (verbose) - fprintf(stderr, "%s: stripped %lld bytes from %s\n", - __progname, st.st_size - footer.orig_size, file); - -done: - if (fd != -1) - close(fd); - return (0); -} - -int -prebind_remove_load_section(int fd, char *name) -{ - Elf_Ehdr *ehdr; - Elf_Phdr *phdr; - int loadsection; - char *buf; - - buf = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_FILE | MAP_SHARED, - fd, 0); - if (buf == MAP_FAILED) { - if (verbose) - warn("%s: cannot mmap for for write", name); - return (-1); - } - - ehdr = (Elf_Ehdr *)buf; - phdr = (Elf_Phdr *)(buf + ehdr->e_phoff); - loadsection = ehdr->e_phnum - 1; - - if (ehdr->e_type != ET_EXEC || - (phdr[loadsection].p_flags & 0x08000000) == 0) - goto done; - - if (phdr[loadsection].p_type != PT_LOAD || - ((phdr[loadsection].p_flags & 0x08000000) == 0)) { - /* doesn't look like ours */ - if (verbose) - fprintf(stderr, "mapped, %s id doesn't match %lx\n", name, - (long)(phdr[loadsection].p_vaddr)); - goto done; - } - - bzero(&phdr[loadsection], sizeof(Elf_Phdr)); - ehdr->e_phnum--; -done: - munmap(buf, 8192); - return (0); -} - -int -prebind_newfile(int infd, char *name, struct stat *st, off_t orig_size) -{ - struct timespec ts[2]; - char *newname, *buf; - ssize_t len, wlen; - int outfd; - - if (asprintf(&newname, "%s.XXXXXXXXXX", name) == -1) { - if (verbose) - warn("asprintf"); - return (-1); - } - outfd = open(newname, O_CREAT|O_RDWR|O_TRUNC, 0600); - if (outfd == -1) { - warn("%s", newname); - free(newname); - return (-1); - } - - buf = malloc(BUFSZ); - if (buf == NULL) { - if (verbose) - warn("malloc"); - goto fail; - } - - /* copy old file to new file */ - lseek(infd, (off_t)0, SEEK_SET); - while (1) { - len = read(infd, buf, BUFSIZ); - if (len == -1) { - if (verbose) - warn("read"); - free(buf); - goto fail; - } - if (len == 0) - break; - wlen = write(outfd, buf, len); - if (wlen != len) { - free(buf); - goto fail; - } - } - free(buf); - close (infd); - - /* now back track, and delete the header */ - if (prebind_remove_load_section(outfd, newname) == -1) - goto fail; - if (orig_size != (off_t)-1 && - ftruncate(outfd, orig_size) == -1) - goto fail; - - /* move new file into place */ - ts[0] = st->st_atimespec; - ts[1] = st->st_mtimespec; - if (futimens(outfd, ts) == -1) - goto fail; - if (fchown(outfd, st->st_uid, st->st_gid) == -1) - goto fail; - if (fchmod(outfd, st->st_mode) == -1) - goto fail; - if (fchflags(outfd, st->st_flags) == -1) - goto fail; - if (rename(newname, name) == -1) - goto fail; - - return (outfd); - -fail: - unlink(newname); - free(newname); - close(outfd); - return (-1); -} diff --git a/libexec/ld.so/ldconfig/prebind_struct.h b/libexec/ld.so/ldconfig/prebind_struct.h deleted file mode 100644 index 0b5dfe7365b..00000000000 --- a/libexec/ld.so/ldconfig/prebind_struct.h +++ /dev/null @@ -1,86 +0,0 @@ -/* $OpenBSD: prebind_struct.h,v 1.3 2006/06/15 22:09:32 drahn Exp $ */ -/* - * Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -struct symcache_noflag { - const elf_object_t *obj; - const Elf_Sym *sym; -}; - -struct objlist { - TAILQ_ENTRY(objlist) list; - TAILQ_ENTRY(objlist) inst_list; - struct elf_object *load_prog; - struct elf_object *object; -}; - -struct proglist { - TAILQ_ENTRY(proglist) list; - TAILQ_HEAD(, objlist) curbin_list; - struct fixup **fixup; - int *fixupcnt; - int *fixupcntalloc; - int nobj; - u_int32_t **libmap; - u_int32_t *libmapcnt; - char *interp; -}; -extern struct proglist *curbin; -extern struct elf_object *load_object; - -typedef TAILQ_HEAD(, proglist) prog_list_ty; -typedef TAILQ_HEAD(, objlist) obj_list_ty; - -extern obj_list_ty library_list; -extern prog_list_ty prog_list; - -/* debug */ -void elf_print_curbin_list(struct proglist *bin); -void elf_print_prog_list (prog_list_ty *prog_list); - -void elf_add_object_curbin_list(struct elf_object *object); - -void elf_copy_syms(struct symcache_noflag *tcache, - struct symcache_noflag *scache, struct elf_object *obj, - struct elf_object *prog, int nsyms); -int elf_prep_lib_prebind(struct elf_object *object); -int elf_prep_bin_prebind(struct proglist *pl); -void elf_calc_fixups(struct proglist *pl, struct objlist *ol, int libidx); -int elf_write_lib(struct elf_object *object, struct nameidx *nameidx, - char *nametab, int nametablen, int numlibs, - int nfixup, struct fixup **fixup, int *fixupcnt, - u_int32_t **libmap, int *libmapcnt, - struct symcachetab *symcachetab, int symcache_cnt, - struct symcachetab *pltsymcachetab, int pltsymcache_cnt); - -void dump_symcachetab(struct symcachetab *symcachetab, int symcache_cnt, - struct elf_object *object, int id); -void dump_info(struct elf_object *object); -void elf_clear_prog_load(int fd, struct elf_object *object); -void elf_fixup_prog_load(int fd, struct prebind_footer *footer, - struct elf_object *object); -void elf_dump_footer(struct prebind_footer *footer); - -extern int verbose; -extern int merge; -extern int safe; - -extern int64_t prebind_blocks; -extern struct elf_object *load_object; -struct elf_object *elf_lookup_object(const char *name); -struct elf_object *load_file(const char *filename, int objtype); - -void elf_load_existing_prebind(struct elf_object *object, int fd); |