diff options
Diffstat (limited to 'utils/env_dump/libs.c')
-rw-r--r-- | utils/env_dump/libs.c | 451 |
1 files changed, 0 insertions, 451 deletions
diff --git a/utils/env_dump/libs.c b/utils/env_dump/libs.c deleted file mode 100644 index 92025d7..0000000 --- a/utils/env_dump/libs.c +++ /dev/null @@ -1,451 +0,0 @@ -/* Copyright (c) 2015, Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define _GNU_SOURCE - -#include "env_dump.h" - -#include <openssl/sha.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <pthread.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <link.h> - -static pthread_mutex_t found_so_list_mp = PTHREAD_MUTEX_INITIALIZER; -size_t shared_object_count = 0; -struct shared_object { - char *full_path; - /* more here? */ -} *found_so_list = NULL; - -void *handle_libcrypto = NULL; -unsigned char *(*SHA1_local)(const unsigned char *d, size_t n, unsigned char *md); - - -struct fll_data { - const char *name; - size_t len_name; - char *ret; -}; - -static int -find_Linked_library_callback(struct dl_phdr_info *info, size_t size, void *data) -{ - struct fll_data *p = (struct fll_data *) data; - size_t len = strlen(info->dlpi_name); - size_t offset = len - p->len_name; - - if (len < p->len_name) - return 0; - - if (strcmp(info->dlpi_name + offset, p->name) == 0) { - p->ret = strdup(info->dlpi_name); - return 1; - } - - return 0; -} - -static char * -find_Linked_library(const char *name) -{ - struct fll_data data = {name, strlen(name), NULL}; - - dl_iterate_phdr(find_Linked_library_callback, &data); - - return data.ret; -} - -static int -libcrypto_resolve_symbols() -{ - void *(*orig_dlopen)(const char *, int); - - if (handle_libcrypto == NULL) { - orig_dlopen = _env_dump_resolve_symbol_by_name("dlopen"); - - /* Open a local version of the libcrypto */ - handle_libcrypto = orig_dlopen("libcrypto.so", - RTLD_LOCAL | RTLD_LAZY); - if (handle_libcrypto) - SHA1_local = dlsym(handle_libcrypto, "SHA1"); - } - - return !handle_libcrypto && !SHA1_local; -} - -void -_env_dump_compute_and_print_sha1(const char *full_path) -{ - unsigned char hash[SHA_DIGEST_LENGTH]; - unsigned char *data; - off_t size; - int fd, i; - - /* this function can be called before init(), so let's check if the - * libcrypto has been loaded or not yet. - */ - if (libcrypto_resolve_symbols()) { - fprintf(env_file, "ERR_MISSING_LIBCRYPTO"); - } else { - fd = open(full_path, O_RDONLY); - size = lseek(fd, 0, SEEK_END); - data = mmap (0, size, PROT_READ, MAP_PRIVATE, fd, 0); - if (data == MAP_FAILED) { - fprintf(env_file, "UNK"); - return; - } - - SHA1_local(data, size, hash); - - for (i = 0; i < 20; i++) { - fprintf(env_file, "%02x", hash[i]); - } - - munmap(data, size); - close(fd); - } -} - -static int -add_so_to_found_list(const char *full_path, const char *when) -{ - int ret = 0, i; - - pthread_mutex_lock(&found_so_list_mp); - found_so_list = realloc(found_so_list, - sizeof(struct shared_object) * (shared_object_count + 1)); - if (found_so_list) { - /* look for already-existing entries */ - for (i = 0; i < shared_object_count; i++) { - if (strcmp(found_so_list[i].full_path, full_path) == 0) { - ret = -1; - goto done; - } - } - - /* we could not find an already-existing entry, add a new one */ - found_so_list[shared_object_count].full_path = strdup(full_path); - shared_object_count++; - - /* report the finding */ - fprintf(env_file, "%s,%s,", when, full_path); - _env_dump_compute_and_print_sha1(full_path); - fprintf(env_file, "\n"); - } else - fprintf(env_file, "ERROR,add_so_to_found_list,realloc\n"); - -done: - pthread_mutex_unlock(&found_so_list_mp); - return ret; -} - -static int -ldd_callback(struct dl_phdr_info *info, size_t size, void *data) -{ - if (strlen(info->dlpi_name) == 0) - return 0; - - add_so_to_found_list(info->dlpi_name, "BOOTLINK"); - - return 0; -} - -static int -new_deps_callback(struct dl_phdr_info *info, size_t size, void *data) -{ - if (strlen(info->dlpi_name) == 0) - return 0; - - add_so_to_found_list(info->dlpi_name, "DYNLINK"); - - return 0; -} - -static void -_dlopen_check_result(void *handle, const char *filename, int flag) -{ - char *full_path; - struct link_map *lm; - - if (!handle || !filename) - return; - - dlinfo(handle, RTLD_DI_LINKMAP, &lm); - full_path = realpath(lm->l_name, NULL); - - add_so_to_found_list(full_path, "DYNLINK"); - - free(full_path); - - /* check if we pulled-in more deps */ - dl_iterate_phdr(new_deps_callback, NULL); -} - -void * -dlopen(const char *filename, int flags) -{ - void *(*orig_dlopen)(const char *, int); - void *handle = NULL; - - orig_dlopen = _env_dump_resolve_symbol_by_name("dlopen"); - - handle = orig_dlopen(filename, flags); - _dlopen_check_result(handle, filename, flags); - - return handle; -} - -void * -dlmopen(Lmid_t lmid, const char *filename, int flags) -{ - void *(*orig_dlmopen)(Lmid_t, const char *, int); - void *handle; - - orig_dlmopen = _env_dump_resolve_symbol_by_name("dlmopen"); - - handle = orig_dlmopen(lmid, filename, flags); - _dlopen_check_result(handle, filename, flags); - - return handle; -} - -static pthread_mutex_t symbols_mp = PTHREAD_MUTEX_INITIALIZER; -size_t symbols_count = 0; -size_t symbols_len = 0; -struct symbol_t { - const char *name; - void *ptr; -} *symbols; - -const char *symbol_key_str[SYMB_END] = { - "ioctl", - "glXSwapBuffers", - "eglSwapBuffers", - "glXMakeCurrent", - "eglMakeCurrent", -}; - -extern void *_dl_sym(void *, const char *, void *); -void * -_env_dump_resolve_symbol_by_name(const char *symbol) -{ - void *ret = NULL; - int i; - - pthread_mutex_lock(&symbols_mp); - - /* first check in our internal DB */ - for (i = 0; i < symbols_count; i++) { - if (symbols[i].name && strcmp(symbols[i].name, symbol) == 0) { - ret = symbols[i].ptr; - break; - } - } - - pthread_mutex_unlock(&symbols_mp); - - /* Then try to see if there is another version somewhere else */ - if (ret == NULL) - ret = _dl_sym(RTLD_NEXT, symbol, _env_dump_resolve_symbol_by_name); - - return ret; -} - -void * -_env_dump_resolve_symbol_by_id(enum symbol_key_t symbol) -{ - void *ret = NULL; - - pthread_mutex_lock(&symbols_mp); - if (symbol < SYMB_END && symbols_len > symbol && symbols[symbol].name) - ret = symbols[symbol].ptr; - pthread_mutex_unlock(&symbols_mp); - - /* Then try to see if there is another version somewhere else */ - if (ret == NULL) { - ret = _dl_sym(RTLD_NEXT, symbol_key_str[symbol], _env_dump_resolve_symbol_by_name); - _env_dump_replace_symbol(symbol_key_str[symbol], ret); - } - - return ret; -} - -void -_env_dump_replace_symbol(const char *symbol, void *ptr) -{ - int size, offset = -1, i; - - pthread_mutex_lock(&symbols_mp); - - /* first check if the symbol is known */ - for (i = 0; i < SYMB_END; i++) { - if (strcmp(symbol_key_str[i], symbol) == 0) { - offset = i; - goto write_offset; - } - } - - /* check if the symbol is already in the list */ - for (i = SYMB_END; i < symbols_count; i++) { - if (strcmp(symbols[i].name, symbol) == 0) { - offset = i; - goto write_offset; - } - } - - /* we need to add the symbol, compute its offset */ - offset = (symbols_count < SYMB_END) ? SYMB_END : symbols_count; - -write_offset: - /* make sure we have enough space allocated */ - if (offset >= symbols_len) { - void *prev = symbols; - size_t start, len; - int bs = 100; - - if (symbols_len == 0) - size = SYMB_END + bs; - else - size = symbols_len + bs; - - symbols = realloc(symbols, size * sizeof(struct symbol_t)); - symbols_len = size; - - if (!prev) { - start = 0; - len = size; - } else { - start = size - bs; - len = bs; - } - - memset(symbols + start, '\0', len * sizeof(struct symbol_t)); - - } - - /* if we are not merely updating an entry */ - if (!symbols[offset].name) - symbols[offset].name = strdup(symbol); - symbols[offset].ptr = ptr; - - /* increase the symbol count after adding an entry */ - if (offset >= symbols_count) - symbols_count = offset + 1; - - pthread_mutex_unlock(&symbols_mp); -} - -void * -_env_dump_resolve_local_symbol_by_name(const char *symbol) -{ - static void *(*orig_dlsym)(void *, const char *); - static void *handle_env_dump; - - if (orig_dlsym == NULL) - orig_dlsym = _dl_sym(RTLD_NEXT, "dlsym", dlsym); - - if (handle_env_dump == NULL ) { - void *(*orig_dlopen)(const char *, int); - char *fullpath = find_Linked_library("env_dump.so"); - orig_dlopen = _dl_sym(RTLD_NEXT, "dlopen", dlsym); - handle_env_dump = orig_dlopen(fullpath, RTLD_LAZY); - free(fullpath); - } - - return orig_dlsym(handle_env_dump, symbol); -} - -/* check which symbols the program looks up */ -void * -dlsym(void *handle, const char *symbol) -{ - static void *(*orig_dlsym)(void *, const char *); - void *orig_ptr, *ptr; - - if (orig_dlsym == NULL) - orig_dlsym = _dl_sym(RTLD_NEXT, "dlsym", dlsym); - - /* try to resolve the symbol to an internal one first to avoid issues - * with dlerror(). - */ - ptr = _env_dump_resolve_local_symbol_by_name(symbol); - - /* resolve the symbol as expected by the client */ - orig_ptr = orig_dlsym(handle, symbol); - if (!orig_ptr) - return orig_ptr; - - /* add the symbol to our DB */ - _env_dump_replace_symbol(symbol, orig_ptr); - - if (ptr) - return ptr; - else - return orig_ptr; -} - -/*int dlclose(void *handle) -{ - int(*orig_dlclose)(void *); - orig_dlclose = _env_dump_resolve_symbol_by_name("dlclose"); - - return orig_dlclose(handle); -}*/ - -void -_env_dump_libs_init() -{ - /* Show what we are currently linking against */ - dl_iterate_phdr(ldd_callback, NULL); -} - -void -_env_dump_libs_fini() -{ - size_t i; - - /* free the memory we do not need anymore */ - pthread_mutex_lock(&found_so_list_mp); - for (i = 0; i < shared_object_count; i++) - free(found_so_list[i].full_path); - shared_object_count = 0; - free(found_so_list); - pthread_mutex_unlock(&found_so_list_mp); - - /* free the symbols */ - pthread_mutex_lock(&symbols_mp); - symbols_count = 0; - free(symbols); - pthread_mutex_unlock(&symbols_mp); - - if (handle_libcrypto) - dlclose(handle_libcrypto); -} |