diff --git a/examples/Makefile b/examples/Makefile index b869b59..ef72a2d 100755 --- a/examples/Makefile +++ b/examples/Makefile @@ -3,7 +3,6 @@ all: $(CC) -O0 -g -fPIC -pie elfparse.c ../src/libelfmaster.a -o elfparse $(CC) -O0 -g merged.c ../src/libelfmaster.a -o merged $(CC) -O0 -g ldd.c ../src/libelfmaster.a -o ldd - $(CC) -O0 -g ldd2.c ../src/libelfmaster.a -o ldd2 $(CC) -O2 -g read_mem.c ../src/libelfmaster.a -o read_mem $(CC) -O2 -g plt_dump.c ../src/libelfmaster.a -o plt_dump $(CC) -O2 -g plt_dump2.c ../src/libelfmaster.a -o plt_dump2 diff --git a/examples/ldd.c b/examples/ldd.c index 2b33ca8..c368b13 100755 --- a/examples/ldd.c +++ b/examples/ldd.c @@ -19,13 +19,14 @@ int main(int argc, char **argv) exit(EXIT_SUCCESS); } - if (elf_open_object(argv[1], &obj, ELF_LOAD_F_FORENSICS, &error) == false) { + if (elf_open_object(argv[1], &obj, ELF_LOAD_F_LXC_MODE|ELF_LOAD_F_FORENSICS, &error) == false) { fprintf(stderr, "%s\n", elf_error_msg(&error)); return -1; } + elf_lxc_set_rootfs(&obj, "/cont/arch/rootfs"); if (elf_shared_object_iterator_init(&obj, &so_iter, - NULL, ELF_SO_LDSO_FAST_F|ELF_SO_IGNORE_VDSO_F|ELF_SO_RESOLVE_F, &error) == false) { + "/cont/arch/rootfs/etc/ld.so.cache", /*ELF_SO_LDSO_FAST_F|ELF_SO_IGNORE_VDSO_F|*/ELF_SO_RESOLVE_F|ELF_SO_RESOLVE_ALL_F, &error) == false) { fprintf(stderr, "elf_shared_object_iterator_init failed: %s\n", elf_error_msg(&error)); return -1; diff --git a/include/libelfmaster.h b/include/libelfmaster.h index 964c05b..976603b 100644 --- a/include/libelfmaster.h +++ b/include/libelfmaster.h @@ -86,6 +86,8 @@ #define ELF_ERRNO_INVALMAGIC 0 #define ELF_ERRNO_INVALSHDRS 1 +#define ELF_LXC_ROOTFS_VAR "LXC_ROOTFS_VAR_LIBELFMASTER" + typedef struct elf_error { char string[MAX_ERROR_STR_LEN]; int _errno; @@ -560,6 +562,7 @@ typedef struct elf_shared_object_iterator { #define ELF_LOAD_F_MODIFY (1UL << 3) //Used for modifying binaries #define ELF_LOAD_F_ULEXEC (1UL << 4) //Used for ulexec based debugging API #define ELF_LOAD_F_MAP_WRITE (1UL << 5) +#define ELF_LOAD_F_LXC_MODE (1UL << 6) // Used when scanning binaries within an LXC container /* * Loads an ELF object of any type, for reading or modifying. @@ -977,4 +980,13 @@ bool elf_dynsym_commit(elfobj_t *); * freeing the existing internal representation and then sorting a new array of strings. */ bool elf_section_commit(elfobj_t *); + +/* + * Set the environment variable that libelfmaster reads to get + * the LXC containers rootfs in order to resolve shared libaries + * from this location internally. + */ +bool elf_lxc_set_rootfs(elfobj_t *, const char *); +bool elf_lxc_get_rootfs(elfobj_t *, char *, const size_t); + #endif diff --git a/src/internal.c b/src/internal.c index 5c0a57b..1678512 100755 --- a/src/internal.c +++ b/src/internal.c @@ -42,6 +42,8 @@ #include "dwarf.h" #include "misc.h" +static char * +ldso_strdup(struct elf_shared_object_iterator *, const char *); /* * TODO Why is this defined in internal.c? @@ -508,6 +510,18 @@ ldso_cache_bsearch(struct elf_shared_object_iterator *iter, right = middle - 1; } } + + if (iter->obj->load_flags & ELF_LOAD_F_LXC_MODE) { + char lxc_path[PATH_MAX]; + + if (elf_lxc_get_rootfs(iter->obj, lxc_path, PATH_MAX / 2) == false) { + if (strlen(lxc_path) + strlen(best) >= PATH_MAX) + return false; + } + strcat(lxc_path, best); + best = ldso_strdup(iter, lxc_path); + } + return best; } @@ -660,10 +674,9 @@ ldso_recursive_cache_resolve(struct elf_shared_object_iterator *iter, * object iterator will use the linked list cache. */ current->path = ldso_strdup(iter, path); - if (current->path == NULL) { + if (current->path == NULL) goto err; - } - if (ldso_insert_yield_entry(iter, current->path) == false){ + if (ldso_insert_yield_entry(iter, current->path) == false) { goto err; } if (ldso_recursive_cache_resolve(iter, current->basename) == false){ diff --git a/src/libelfmaster.c b/src/libelfmaster.c index f4e15d2..6f154b1 100644 --- a/src/libelfmaster.c +++ b/src/libelfmaster.c @@ -54,6 +54,33 @@ (((addr) + __alignof__ (struct cache_file_new) -1) \ & (~(__alignof__ (struct cache_file_new) - 1))) +bool +elf_lxc_set_rootfs(elfobj_t *obj, const char *lxcpath) +{ + if ((obj->load_flags & ELF_LOAD_F_LXC_MODE) == false) { + return true; + } + if (setenv(ELF_LXC_ROOTFS_VAR, lxcpath, 1) == 0) + return true; + return false; +} + +bool +elf_lxc_get_rootfs(elfobj_t *obj, char *out, const size_t maxlen) +{ + char *v = secure_getenv(ELF_LXC_ROOTFS_VAR); + + (void) obj; + + if (maxlen > PATH_MAX) + return false; + if (strlen(v) > maxlen - 1) + return false; + strncpy(out, v, maxlen); + out[maxlen - 1] = '\0'; + return true; +} + bool elf_symtab_count(elfobj_t *obj, uint64_t *count) { @@ -1520,17 +1547,17 @@ elf_shared_object_iterator_init(struct elfobj *obj, } iter->fd = open(cache_file, O_RDONLY); if (iter->fd < 0) { - return elf_error_set(error, "open %s: %s", CACHE_FILE, + return elf_error_set(error, "open %s: %s", cache_file, strerror(errno)); } if (fstat(iter->fd, &iter->st) < 0) { - return elf_error_set(error, "fstat %s: %s", CACHE_FILE, + return elf_error_set(error, "fstat %s: %s", cache_file, strerror(errno)); } iter->mem = mmap(NULL, iter->st.st_size, PROT_READ, MAP_PRIVATE, iter->fd, 0); if (iter->mem == MAP_FAILED) { - return elf_error_set(error, "mmap %s: %s", CACHE_FILE, + return elf_error_set(error, "mmap %s: %s", cache_file, strerror(errno)); } iter->cache = iter->mem;