X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fprocd.git;a=blobdiff_plain;f=jail%2Felf.c;h=7c6076afb6a7f305695163ede2a796af73f9cd5e;hp=46c19df728ef5654b0c6ada58087d1a69ebeeed1;hb=79bbe6daf70feb27ec0e2060b86852015cd04465;hpb=346152decc4aa3a5521047f3493127b64daa8098 diff --git a/jail/elf.c b/jail/elf.c index 46c19df..7c6076a 100644 --- a/jail/elf.c +++ b/jail/elf.c @@ -12,14 +12,10 @@ */ #define _GNU_SOURCE -#include -#include -#include #include #include #include -#include #include #include #include @@ -27,6 +23,7 @@ #include #include "elf.h" +#include "fs.h" #include "log.h" struct avl_tree libraries; @@ -52,7 +49,11 @@ static void alloc_library_path(const char *path) DEBUG("adding ld.so path %s\n", path); } -static void alloc_library(const char *path, const char *name) +/* + * path = full path + * name = soname/avl key + */ +void alloc_library(const char *path, const char *name) { struct library *l; char *_name, *_path; @@ -67,47 +68,38 @@ static void alloc_library(const char *path, const char *name) l->path = strcpy(_path, path); avl_insert(&libraries, &l->avl); - DEBUG("adding library %s/%s\n", path, name); + DEBUG("adding library %s (%s)\n", path, name); } -static int elf_open(char **dir, const char *file) +int lib_open(char **fullpath, const char *file) { struct library_path *p; char path[PATH_MAX]; int fd = -1; - *dir = NULL; + *fullpath = NULL; list_for_each_entry(p, &library_paths, list) { - if (strlen(p->path)) - snprintf(path, sizeof(path), "%s/%s", p->path, file); - else - strncpy(path, file, sizeof(path)); - fd = open(path, O_RDONLY); + snprintf(path, sizeof(path), "%s/%s", p->path, file); + fd = open(path, O_RDONLY|O_CLOEXEC); if (fd >= 0) { - *dir = p->path; + *fullpath = strdup(path); break; } } - if (fd == -1) - fd = open(file, O_RDONLY); - return fd; } const char* find_lib(const char *file) { struct library *l; - static char path[PATH_MAX]; l = avl_find_element(&libraries, file, l, avl); if (!l) return NULL; - snprintf(path, sizeof(path), "%s/%s", l->path, file); - - return path; + return l->path; } static int elf64_find_section(const char *map, unsigned int type, unsigned int *offset, unsigned int *size, unsigned int *vaddr) @@ -197,7 +189,7 @@ static int elf32_scan_dynamic(const char *map, int dyn_offset, int dyn_size, int if (curr->d_tag != DT_NEEDED) continue; - if (elf_load_deps(&strtab[curr->d_un.d_val])) + if (add_path_and_deps(&strtab[curr->d_un.d_val], 1, -1, 1)) return -1; } @@ -231,79 +223,42 @@ static int elf64_scan_dynamic(const char *map, int dyn_offset, int dyn_size, int if (curr->d_tag != DT_NEEDED) continue; - if (elf_load_deps(&strtab[curr->d_un.d_val])) + if (add_path_and_deps(&strtab[curr->d_un.d_val], 1, -1, 1)) return -1; } return 0; } -int elf_load_deps(const char *library) +int elf_load_deps(const char *path, const char *map) { unsigned int dyn_offset, dyn_size; unsigned int load_offset, load_vaddr; - struct stat s; - char *map = NULL, *dir = NULL; - int clazz, fd, ret = -1; - - if (avl_find(&libraries, library)) - return 0; - - fd = elf_open(&dir, library); - - if (fd < 0) { - ERROR("failed to open %s\n", library); - return -1; - } - - if (fstat(fd, &s) == -1) { - ERROR("failed to stat %s\n", library); - ret = -1; - goto err_out; - } - - map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (map == MAP_FAILED) { - ERROR("failed to mmap %s\n", library); - ret = -1; - goto err_out; - } + unsigned int interp_offset; if (elf_find_section(map, PT_LOAD, &load_offset, NULL, &load_vaddr)) { - ERROR("failed to load the .load section from %s\n", library); - ret = -1; - goto err_out; + ERROR("failed to load the .load section from %s\n", path); + return -1; } if (elf_find_section(map, PT_DYNAMIC, &dyn_offset, &dyn_size, NULL)) { - ERROR("failed to load the .dynamic section from %s\n", library); - ret = -1; - goto err_out; + ERROR("failed to load the .dynamic section from %s\n", path); + return -1; } - if (dir) { - alloc_library(dir, library); - } else { - char *elf1 = strdup(library); - char *elf2 = strdup(library); - - alloc_library(dirname(elf1), basename(elf2)); - free(elf1); - free(elf2); + if (elf_find_section(map, PT_INTERP, &interp_offset, NULL, NULL) == 0) { + add_path_and_deps(map+interp_offset, 1, -1, 0); } - clazz = map[EI_CLASS]; + + int clazz = map[EI_CLASS]; if (clazz == ELFCLASS32) - ret = elf32_scan_dynamic(map, dyn_offset, dyn_size, load_vaddr - load_offset); + return elf32_scan_dynamic(map, dyn_offset, dyn_size, load_vaddr - load_offset); else if (clazz == ELFCLASS64) - ret = elf64_scan_dynamic(map, dyn_offset, dyn_size, load_vaddr - load_offset); - -err_out: - if (map) - munmap(map, s.st_size); - close(fd); + return elf64_scan_dynamic(map, dyn_offset, dyn_size, load_vaddr - load_offset); - return ret; + ERROR("unknown elf format %d\n", clazz); + return -1; } static void load_ldso_conf(const char *conf)