From 8306ee65705c09d5e31a505fe44d42a455626f8e Mon Sep 17 00:00:00 2001 From: Andrei Lascu Date: Fri, 1 Nov 2024 10:31:35 +0000 Subject: [PATCH] 1 compartment to N mappings Move from a design of "one compartment has one mapping" to "one compartment can be mapped multiple times". This involves "staging" a compartment, with temporary internal relative relocations, after which the staging can be lifted to a "mapping", which has correct relocations and can be executed. This greatly reduces the overhead of creating the same compartment multiple times. * Remove some now unused functions --- include/compartment.h | 23 +- include/intercept.h | 7 +- include/manager.h | 23 +- src/compartment.c | 438 +++++++++++++------------------- src/intercept.c | 18 +- src/manager.c | 276 ++++++++++++++------ tests/CMakeLists.txt | 18 +- tests/compartment_harness.c | 109 ++++++-- tests/manager_arg_passer.c | 5 +- tests/manager_caller.c | 5 +- tests/manager_caller_multiple.c | 7 +- tests/simple_fprintf.c | 12 + tests/simple_printf.c | 7 +- tests/test_map.c | 10 +- tests/test_map_multi.c | 6 +- 15 files changed, 551 insertions(+), 413 deletions(-) create mode 100644 tests/simple_fprintf.c diff --git a/include/compartment.h b/include/compartment.h index a9a3d17..e8f5e5b 100644 --- a/include/compartment.h +++ b/include/compartment.h @@ -75,9 +75,7 @@ extern void *__capability comp_return_caps[2]; struct SegmentMap { void *mem_bot; - void *mem_top; size_t offset; - ptrdiff_t correction; size_t mem_sz; size_t file_sz; int prot_flags; @@ -97,6 +95,7 @@ struct LibRelaMapping unsigned short rela_sym_type; // type of underlying symbol unsigned short rela_sym_bind; // bind of underlying symbol uint16_t rela_sym_shndx; // section index of underlying symbol + bool mapping_reloc; // whether to relocate when mapped for execution }; /** @@ -106,7 +105,10 @@ struct LibDependency { char *lib_name; char *lib_path; - void *lib_mem_base; + void *lib_mem_base; // relative address in compartment + + void *data_base; // address of data mapped in loader + size_t data_size; // size of mapped data // Segments of interest (usually, of type `PT_LOAD`) within this library size_t lib_segs_count; @@ -127,6 +129,7 @@ struct LibDependency // TLS-related variables // TODO can there be more TLS sections? void *tls_sec_addr; + size_t tls_sec_off; size_t tls_sec_size; size_t tls_data_size; // offset from TLS base pointer (i.e., value of `tpidr_el0`) where this @@ -167,7 +170,6 @@ struct CompConfig size_t stack_size; struct CompEntryPointDef *entry_points; size_t entry_point_count; - void *base_address; // Variables related to `manager.h` prepared `environ` data char **env_ptr; // pointer to `environ` array @@ -186,12 +188,11 @@ struct Compartment size_t id; struct CompConfig *cc; // Execution info - void *__capability ddc; // ELF data - size_t size; // size of compartment in memory - void *base; // address where to load compartment - void *mem_top; - bool mapped; + size_t total_size; // size of compartment in memory + size_t data_size; // size of data segments of ELF files + void *staged_addr; // address where compartment data is stored, ready for + // mapping // Environ char **environ_ptr; @@ -223,7 +224,7 @@ entry_point_cmp(const void *, const void *); struct Compartment * comp_from_elf(char *, struct CompConfig *); // char **, size_t, void *); void -comp_map(struct Compartment *); +comp_map(struct Compartment *, void *); void comp_unmap(struct Compartment *); void @@ -232,6 +233,8 @@ int64_t comp_exec(struct Compartment *, char *, void *, size_t); void comp_clean(struct Compartment *); +void * +get_seg_target(void *, struct LibDependency *, size_t); struct Compartment * find_comp(struct Compartment *); diff --git a/include/intercept.h b/include/intercept.h index 83531f6..8eed1ec 100644 --- a/include/intercept.h +++ b/include/intercept.h @@ -9,7 +9,9 @@ // vDSO wrapper needed includes #include +#ifdef __CHERI__ #include "cheriintrin.h" +#endif // Forward declarations struct Compartment; @@ -55,7 +57,8 @@ intercept_wrapper(); void setup_intercepts(); -size_t -my_call_comp(size_t, char *, void *); +// TODO Reimplement this for inter-compartment function calls +// size_t +// my_call_comp(size_t, char *, void *); #endif // _INTERCEPT_H diff --git a/include/manager.h b/include/manager.h index d9762e2..084333d 100644 --- a/include/manager.h +++ b/include/manager.h @@ -31,12 +31,8 @@ extern struct Compartment *loaded_comp; // Compartment configuration file suffix extern const char *comp_config_suffix; -void * -get_next_comp_addr(void); struct Compartment * register_new_comp(char *, bool); -int64_t -exec_comp(struct Compartment *, char *, char **); union arg_holder { @@ -57,7 +53,24 @@ void clean_compartment_config(struct CompEntryPointDef *, size_t); /******************************************************************************* - * Memory allocation + * Compartment mappings ******************************************************************************/ +struct CompMapping * +mapping_new(struct Compartment *); +struct CompMapping * +mapping_new_fixed(struct Compartment *, void *); +void +mapping_free(struct CompMapping *); +int64_t +mapping_exec(struct CompMapping *, char *, char **); + +struct CompMapping +{ + size_t id; + void *__capability ddc; + void *map_addr; + struct Compartment *comp; +}; + #endif // _MANAGER_H diff --git a/src/compartment.c b/src/compartment.c index 392a3ab..c524b6b 100644 --- a/src/compartment.c +++ b/src/compartment.c @@ -35,14 +35,14 @@ find_tls_lookup_func(struct Compartment *); static bool check_lib_dep_sym(lib_symbol *, const unsigned short); static void * +eval_staged_sym_offset(struct Compartment *, const comp_symbol *); +static void * +eval_staged_sym_tls_offset(struct Compartment *, const comp_symbol *); +static void * eval_sym_offset(struct Compartment *, const comp_symbol *); static void * eval_lib_sym_offset(struct Compartment *, const size_t, const lib_symbol *); -static void * -eval_sym_tls_offset(struct Compartment *, const comp_symbol *); -static ssize_t -do_pread(int, void *, size_t, off_t); static void get_lib_data(void *, void *, size_t, off_t); static void * @@ -59,11 +59,15 @@ static void setup_environ(struct Compartment *); static void resolve_comp_tls_regions(struct Compartment *); +static void +stage_comp(struct Compartment *); static void print_lib_dep_seg(struct SegmentMap *); static void print_lib_dep(struct LibDependency *); +static void +print_comp_simple(struct Compartment *); /******************************************************************************* * Main compartment functions @@ -78,12 +82,9 @@ comp_init() // TODO order struct Compartment *new_comp = malloc(sizeof(struct Compartment)); - new_comp->ddc = NULL; - - new_comp->size = 0; - new_comp->base = NULL; - new_comp->mem_top = NULL; - new_comp->mapped = false; + new_comp->total_size = 0; + new_comp->data_size = 0; + new_comp->staged_addr = NULL; new_comp->scratch_mem_base = NULL; new_comp->scratch_mem_size = 0; @@ -125,6 +126,7 @@ lib_init() new_lib->rela_maps = NULL; new_lib->tls_sec_addr = 0x0; + new_lib->tls_sec_off = 0; new_lib->tls_sec_size = 0; new_lib->tls_data_size = 0; new_lib->tls_offset = 0; @@ -140,8 +142,6 @@ comp_from_elf(char *filename, struct CompConfig *cc) { struct Compartment *new_comp = comp_init(); new_comp->cc = cc; - new_comp->base = cc->base_address; // TODO reuse `cc` base - new_comp->mem_top = cc->base_address; unsigned short libs_to_parse_count = 1; unsigned short libs_parsed_count = 0; @@ -177,19 +177,29 @@ comp_from_elf(char *filename, struct CompConfig *cc) assert(cc->entry_points); assert(cc->entry_point_count > 0); + new_comp->total_size += align_up( + new_comp->data_size + new_comp->page_size, new_comp->page_size); init_comp_scratch_mem(new_comp); setup_environ(new_comp); map_comp_entry_points(new_comp); resolve_comp_tls_regions(new_comp); + + // Update total compartment size, by adding additional scratch + extra + // (TLS, environ) memory needs + new_comp->total_size += new_comp->scratch_mem_size; + + // All data collected; map compartment to a staging area ... + stage_comp(new_comp); + + // ... and perform relocations resolve_rela_syms(new_comp); // Compartment size sanity check - assert(new_comp->mem_top - == (char *) new_comp->base + // base compartment address - new_comp->size + // size of loaded ELF files - new_comp->page_size - + // buffer between scratch memory and compartment libraries + assert(new_comp->total_size + == align_up(new_comp->data_size, new_comp->page_size) + + // size of loaded ELF files + new_comp->page_size + // buffer new_comp->scratch_mem_size // size of scratch memory ); assert(new_comp->scratch_mem_size % new_comp->page_size == 0); @@ -206,196 +216,13 @@ comp_from_elf(char *filename, struct CompConfig *cc) assert(new_comp->environ_sz + new_comp->total_tls_size == new_comp->scratch_mem_extra); + print_comp_simple(new_comp); return new_comp; } -/* Map a struct Compartment into memory, making it ready for execution - */ -void -comp_map(struct Compartment *to_map) -{ - assert(!(to_map->mapped)); - struct SegmentMap *curr_seg; - - // Map compartment library dependencies segments - struct LibDependency *lib_dep; - struct SegmentMap lib_dep_seg; - int lib_dep_fd; - - void *map_result = mmap(to_map->base, - (intptr_t) ((char *) to_map->mem_top - (char *) to_map->base), - PROT_READ | PROT_WRITE | PROT_EXEC, // TODO fix - MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); - if (map_result == MAP_FAILED) - { - err(1, "Error mapping compartment %zu data", to_map->id); - } - - for (size_t i = 0; i < to_map->libs_count; ++i) - { - lib_dep = to_map->libs[i]; - lib_dep_fd = open(lib_dep->lib_path, O_RDONLY); - for (size_t j = 0; j < lib_dep->lib_segs_count; ++j) - { - lib_dep_seg = lib_dep->lib_segs[j]; - do_pread(lib_dep_fd, - (char *) lib_dep->lib_mem_base - + (uintptr_t) lib_dep_seg.mem_bot, - lib_dep_seg.file_sz, lib_dep_seg.offset); - } - close(lib_dep_fd); - } - - // Map compartment scratch memory - heap, stack, sealed manager - // capabilities for transition out, capabilities to call other compartments - // (TODO fix this), TLS region (if applicable) - assert((intptr_t) to_map->scratch_mem_base % to_map->page_size == 0); - assert(to_map->scratch_mem_size % to_map->page_size == 0); - map_result - = mmap((void *) to_map->scratch_mem_base, to_map->scratch_mem_size, - PROT_READ | PROT_WRITE, // | PROT_EXEC, // TODO Fix this - MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); - if (map_result == MAP_FAILED) - { - err(1, "Error mapping compartment %zu scratch memory", to_map->id); - } - - /* Copy over environ variables - * - * We need a pointer to an array of string pointers, so we synthetically - * create one. We don't expect this pointer to move, as the maximum allowed - * size for the `environ` array is already allocated - */ - *to_map->environ_ptr = (char *) (to_map->environ_ptr + 1); - to_map->environ_ptr += 1; - - // Copy over prepared `environ` data from manager - memcpy(to_map->environ_ptr, to_map->cc->env_ptr, to_map->cc->env_ptr_sz); - for (unsigned short i = 0; i < to_map->cc->env_ptr_count; ++i) - { - // Update entry offsets relative to compartment address - *(to_map->environ_ptr + i) += (uintptr_t) to_map->environ_ptr; - } - - size_t tls_allocd = 0x0; - for (size_t i = 0; i < to_map->libs_count; ++i) - { - // Bind `.got.plt` entries - for (size_t j = 0; j < to_map->libs[i]->rela_maps_count; ++j) - { - assert(to_map->libs[i]->rela_maps[j].rela_address != 0); - if (to_map->libs[i]->rela_maps[j].target_func_address == 0) - { - continue; - } - memcpy(to_map->libs[i]->rela_maps[j].rela_address, - &to_map->libs[i]->rela_maps[j].target_func_address, - sizeof(void *)); - } - - // Map .tdata sections - if (to_map->libs[i]->tls_data_size != 0) - { - assert(to_map->libs[i]->tls_sec_addr); - memcpy((char *) to_map->libs_tls_sects->region_start + tls_allocd, - to_map->libs[i]->tls_sec_addr, to_map->libs[i]->tls_data_size); - tls_allocd += to_map->libs[i]->tls_sec_size; - } - } - - to_map->mapped = true; -} - -void -comp_unmap(struct Compartment *to_unmap) -{ - int res; - - res = munmap(to_unmap->base, - (intptr_t) ((char *) to_unmap->mem_top - (char *) to_unmap->base)); - if (res == -1) - { - err(1, "Error unmapping compartment %zu data", to_unmap->id); - } - - res = munmap( - (void *) to_unmap->scratch_mem_base, to_unmap->scratch_mem_size); - if (res == -1) - { - err(1, "Error unmapping compartment %zu scratch memory", to_unmap->id); - } - - to_unmap->mapped = false; -} - -/* Execute a mapped compartment, by jumping to the appropriate entry point. - * - * The entry point is given as a function name in the `fn_name` argument, and - * arguments to be passed are tightly packed in `args`. The requested entry - * point must have been registered prior during compartment initialization, by - * calling `parse_compartment_config`, and passing an appropriate `.comp` - * config file. - * - * TODO casually ignore the situation where no compartment is passed, if we - * prefer to default to `main` in that case - */ -int64_t -comp_exec( - struct Compartment *to_exec, char *fn_name, void *args, size_t args_count) -{ - assert( - to_exec->mapped && "Attempting to execute an unmapped compartment.\n"); - - void *fn = NULL; - for (size_t i = 0; i < to_exec->cc->entry_point_count; ++i) - { - if (!strcmp(fn_name, to_exec->cc->entry_points[i].name)) - { - fn = (void *) to_exec->cc->entry_points[i].comp_addr; - break; - } - } - if (!fn) - { - errx(1, "Did not find entry point `%s`!\n", fn_name); - } - void *wrap_sp; - - // TODO check if we need anything from here - // https://git.morello-project.org/morello/kernel/linux/-/wikis/Morello-pure-capability-kernel-user-Linux-ABI-specification - - int64_t result; - - // TODO handle register clobbering stuff (`syscall-restrict` example) - // https://github.com/capablevms/cheri_compartments/blob/master/code/signal_break.c#L46 - assert(args_count <= 3); - // TODO attempt to lifting pointers to capabilities before passing to - // compartments. Might be needed when handling pointers. - /*void * __capability * args_caps;*/ - /*for (size_t i = 0; i < args_count; ++i)*/ - /*{*/ - /*void* __capability arg = (__cheri_tocap void* __capability) args[i];*/ - /*arg = cheri_perms_and(arg, !(CHERI_PERM_STORE | CHERI_PERM_EXECUTE));*/ - /*args_caps[i] = arg;*/ - /*}*/ - // TODO - // * set TPIDR_EL0 to TLS start, if given - // * make `tls_lookup_stub` get the index - // * fix statics? - result = comp_exec_in(to_exec->scratch_mem_stack_top, to_exec->ddc, fn, - args, args_count, sealed_redirect_cap, - to_exec->libs_tls_sects->region_start); - return result; -} - void comp_clean(struct Compartment *to_clean) { - if (to_clean->mapped) - { - comp_unmap(to_clean); - } - struct LibDependency *curr_lib_dep; for (size_t i = 0; i < to_clean->libs_count; ++i) { @@ -508,6 +335,8 @@ parse_lib_file(char *lib_name, struct Compartment *new_comp) } struct LibDependency *new_lib = lib_init(); + new_lib->data_base = lib_data; + new_lib->data_size = lib_fd_stat.st_size; new_lib->lib_name = malloc(strlen(lib_name) + 1); strcpy(new_lib->lib_name, lib_name); if (lib_path) @@ -617,6 +446,7 @@ parse_lib_segs(Elf64_Ehdr *lib_ehdr, void *lib_data, new_comp->libs_tls_sects = malloc(sizeof(struct TLSDesc)); } lib_dep->tls_sec_addr = (void *) lib_phdr.p_vaddr; + lib_dep->tls_sec_off = lib_phdr.p_offset; lib_dep->tls_sec_size = lib_phdr.p_memsz; } @@ -626,36 +456,26 @@ parse_lib_segs(Elf64_Ehdr *lib_ehdr, void *lib_data, } struct SegmentMap *this_seg = malloc(sizeof(struct SegmentMap)); - this_seg->mem_bot - = (void *) align_down(lib_phdr.p_vaddr, new_comp->page_size); - this_seg->correction - = (char *) lib_phdr.p_vaddr - (char *) this_seg->mem_bot; - this_seg->mem_top = (char *) lib_phdr.p_vaddr + lib_phdr.p_memsz; - this_seg->offset = align_down(lib_phdr.p_offset, new_comp->page_size); - this_seg->mem_sz = lib_phdr.p_memsz + this_seg->correction; - this_seg->file_sz = lib_phdr.p_filesz + this_seg->correction; + this_seg->mem_bot = (void *) lib_phdr.p_vaddr; + this_seg->offset = lib_phdr.p_offset; + this_seg->mem_sz = lib_phdr.p_memsz; + this_seg->file_sz = lib_phdr.p_filesz; this_seg->prot_flags = (lib_phdr.p_flags & PF_R ? PROT_READ : 0) | (lib_phdr.p_flags & PF_W ? PROT_WRITE : 0) | (lib_phdr.p_flags & PF_X ? PROT_EXEC : 0); lib_dep->lib_segs_count += 1; - lib_dep->lib_segs_size - += align_up(this_seg->mem_sz, lib_phdr.p_align); // TODO check + lib_dep->lib_segs_size += align_up(this_seg->mem_sz, lib_phdr.p_align); lib_dep->lib_segs = realloc(lib_dep->lib_segs, lib_dep->lib_segs_count * sizeof(struct SegmentMap)); memcpy(&lib_dep->lib_segs[lib_dep->lib_segs_count - 1], this_seg, sizeof(struct SegmentMap)); free(this_seg); } - lib_dep->lib_mem_base = align_up( - (char *) new_comp->mem_top + new_comp->page_size, new_comp->page_size); - new_comp->size += lib_dep->lib_segs_size; - new_comp->mem_top = (char *) lib_dep->lib_mem_base + lib_dep->lib_segs_size; - if (lib_dep->tls_sec_addr) - { - lib_dep->tls_sec_addr = (char *) lib_dep->tls_sec_addr - + (uintptr_t) lib_dep->lib_mem_base; - } + lib_dep->lib_mem_base + = align_up((char *) new_comp->data_size + new_comp->page_size, + new_comp->page_size); + new_comp->data_size += lib_dep->lib_segs_size; } static void @@ -732,7 +552,7 @@ parse_lib_rela(Elf64_Shdr *rela_shdr, Elf64_Ehdr *lib_ehdr, void *lib_data, // Prepare TLS look-up function relocation (will be copied for each TLS // relocation entry static struct LibRelaMapping tls_lrm - = { NULL, 0x0, 0x0, -1, STT_FUNC, STB_GLOBAL, 0 }; + = { NULL, 0x0, 0x0, -1, STT_FUNC, STB_GLOBAL, 0, true }; // Log symbols that will need to be relocated eagerly at maptime Elf64_Rela curr_rela; @@ -744,7 +564,7 @@ parse_lib_rela(Elf64_Shdr *rela_shdr, Elf64_Ehdr *lib_ehdr, void *lib_data, size_t curr_rela_type = ELF64_R_TYPE(curr_rela.r_info); struct LibRelaMapping lrm - = { NULL, 0x0, 0x0, curr_rela_type, -1, -1, 0 }; + = { NULL, 0x0, 0x0, curr_rela_type, -1, -1, 0, true }; // XXX We handle `TLS` symbols differently. It seems the way // AARCH64 handles TLS variables is preferentially via @@ -813,9 +633,13 @@ parse_lib_rela(Elf64_Shdr *rela_shdr, Elf64_Ehdr *lib_ehdr, void *lib_data, // function relocation lrm.rela_address = curr_rela.r_offset + (char *) lib_dep->lib_mem_base + sizeof(void *); + + // Do not update address in mapping for TLS variables + lrm.mapping_reloc = false; } else if (curr_rela_type == R_AARCH64_TLS_TPREL64) { + lrm.mapping_reloc = false; lrm.target_func_address = (char *) curr_rela.r_addend; lrm.rela_address = curr_rela.r_offset + (char *) lib_dep->lib_mem_base; @@ -935,6 +759,13 @@ map_comp_entry_points(struct Compartment *new_comp) } } +/* Resolve relocations with compartment relative addresses + * + * The way AARCH64 relocations work is that they use relative addresses for the + * lookup, so we only need to resolve the addresses within the compartment, + * without needing to know where the compartment will eventually be mapped in + * actual memory + */ static void resolve_rela_syms(struct Compartment *new_comp) { @@ -943,10 +774,9 @@ resolve_rela_syms(struct Compartment *new_comp) struct LibRelaMapping *curr_rela_map; comp_symbol **candidate_syms; comp_symbol *chosen_sym; - bool lel = true; + void *rela_target; for (size_t i = 0; i < new_comp->libs_count; ++i) { - lel = true; for (size_t j = 0; j < new_comp->libs[i]->rela_maps_count; ++j) { curr_rela_map = &new_comp->libs[i]->rela_maps[j]; @@ -957,14 +787,23 @@ resolve_rela_syms(struct Compartment *new_comp) if (curr_rela_map->rela_sym_type == STT_TLS && curr_rela_map->rela_sym_shndx != 0) { - curr_rela_map->target_func_address + *((void **) ((char *) new_comp->staged_addr + + (uintptr_t) curr_rela_map->rela_address)) = (char *) curr_rela_map->target_func_address + prev_tls_secs_size; continue; } - if (curr_rela_map->target_func_address != 0 - || curr_rela_map->rela_type == R_AARCH64_TLS_TPREL64) + if (curr_rela_map->rela_type == R_AARCH64_TLS_TPREL64) + { + *((void **) ((char *) new_comp->staged_addr + + (uintptr_t) curr_rela_map->rela_address)) + = (char *) curr_rela_map->target_func_address + + prev_tls_secs_size; + continue; + } + + if (curr_rela_map->target_func_address != 0) { continue; } @@ -1053,15 +892,18 @@ resolve_rela_syms(struct Compartment *new_comp) } free(candidate_syms); + // TODO collapse? if (curr_rela_map->rela_sym_type == STT_TLS) { - curr_rela_map->target_func_address - = eval_sym_tls_offset(new_comp, chosen_sym); + rela_target = eval_staged_sym_tls_offset(new_comp, chosen_sym); + memcpy((char *) new_comp->staged_addr + + (uintptr_t) curr_rela_map->rela_address, + &rela_target, sizeof(void *)); } else { curr_rela_map->target_func_address - = eval_sym_offset(new_comp, chosen_sym); + = eval_staged_sym_offset(new_comp, chosen_sym); } } prev_tls_secs_size += new_comp->libs[i]->tls_sec_size; @@ -1085,17 +927,6 @@ find_tls_lookup_func(struct Compartment *comp) * Helper functions ******************************************************************************/ -static ssize_t -do_pread(int fd, void *buf, size_t count, off_t offset) -{ - ssize_t res = pread(fd, buf, count, offset); - if (res == -1) - { - err(1, "Error in pread"); - } - return res; -} - static void get_lib_data(void *buf, void *lib_file_addr, size_t data_sz, off_t offset) { @@ -1108,26 +939,41 @@ seek_lib_data(void *lib_data, off_t offset) return (void *) ((char *) lib_data + offset); } +void * +get_seg_target(void *base_addr, struct LibDependency *lib_dep, size_t seg_id) +{ + return (char *) base_addr + (uintptr_t) lib_dep->lib_mem_base + + (uintptr_t) lib_dep->lib_segs[seg_id].mem_bot; +} + static void * -eval_sym_offset(struct Compartment *comp, const comp_symbol *sym) +eval_staged_sym_offset(struct Compartment *comp, const comp_symbol *sym) { + assert(comp->staged_addr != NULL); return (char *) comp->libs[sym->sym_lib_idx]->lib_mem_base - + (intptr_t) sym->sym_ref->sym_offset; + + (uintptr_t) sym->sym_ref->sym_offset; } static void * -eval_lib_sym_offset( - struct Compartment *comp, const size_t lib_idx, const lib_symbol *sym) +eval_staged_sym_tls_offset(struct Compartment *comp, const comp_symbol *sym) { - return (char *) comp->libs[lib_idx]->lib_mem_base - + (intptr_t) sym->sym_offset; + return (char *) sym->sym_ref->sym_offset + + comp->libs[sym->sym_lib_idx]->tls_offset; // TODO check offset type } static void * -eval_sym_tls_offset(struct Compartment *comp, const comp_symbol *sym) +eval_sym_offset(struct Compartment *comp, const comp_symbol *sym) { - return (char *) sym->sym_ref->sym_offset - + comp->libs[sym->sym_lib_idx]->tls_offset; + return (char *) comp->libs[sym->sym_lib_idx]->lib_mem_base + + (uintptr_t) sym->sym_ref->sym_offset; +} + +static void * +eval_lib_sym_offset( + struct Compartment *comp, const size_t lib_idx, const lib_symbol *sym) +{ + return (char *) comp->libs[lib_idx]->lib_mem_base + + (uintptr_t) sym->sym_offset; } // TODO relocate all `NOTYPE` symbols to same symbol - cache? @@ -1187,9 +1033,7 @@ find_in_dir(const char *const lib_name, char *search_dir) static void init_comp_scratch_mem(struct Compartment *new_comp) { - new_comp->scratch_mem_base = align_up( - (char *) new_comp->base + new_comp->size + new_comp->page_size, - new_comp->page_size); + new_comp->scratch_mem_base = (void *) new_comp->total_size; new_comp->scratch_mem_heap_size = new_comp->cc->heap_size; new_comp->scratch_mem_stack_size = new_comp->cc->stack_size; new_comp->scratch_mem_stack_top = align_down( @@ -1199,10 +1043,6 @@ init_comp_scratch_mem(struct Compartment *new_comp) new_comp->scratch_mem_size = new_comp->scratch_mem_heap_size + new_comp->scratch_mem_stack_size; - new_comp->mem_top = (char *) new_comp->mem_top - + ((char *) new_comp->scratch_mem_base - (char *) new_comp->mem_top) - + new_comp->scratch_mem_size; - assert((uintptr_t) new_comp->scratch_mem_base % new_comp->page_size == 0); assert( (((uintptr_t) new_comp->scratch_mem_base) + new_comp->scratch_mem_size) @@ -1223,7 +1063,6 @@ adjust_comp_scratch_mem(struct Compartment *new_comp, size_t to_adjust) new_comp->scratch_mem_size += to_adjust; new_comp->scratch_mem_stack_top = (char *) new_comp->scratch_mem_stack_top + to_adjust; - new_comp->mem_top = (char *) new_comp->mem_top + to_adjust; new_comp->scratch_mem_extra += to_adjust; } @@ -1288,16 +1127,79 @@ resolve_comp_tls_regions(struct Compartment *new_comp) new_comp->libs_tls_sects->region_size = comp_tls_size; } +static void +stage_comp(struct Compartment *to_stage) +{ + void *base_stage_addr = mmap(NULL, to_stage->total_size, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (base_stage_addr == MAP_FAILED) + { + err(1, "Error staging compartment %zu", to_stage->id); + } + + // Copy over segment data and `.tdata` + struct LibDependency *lib_dep; + struct SegmentMap lib_dep_seg; + size_t tls_allocd = 0x0; + for (size_t i = 0; i < to_stage->libs_count; ++i) + { + lib_dep = to_stage->libs[i]; + + // Segment data + for (size_t j = 0; j < lib_dep->lib_segs_count; ++j) + { + lib_dep_seg = lib_dep->lib_segs[j]; + memcpy(get_seg_target(base_stage_addr, lib_dep, j), + (char *) lib_dep->data_base + lib_dep_seg.offset, + lib_dep_seg.file_sz); + } + + // `.tdata` for TLS + if (to_stage->libs[i]->tls_sec_size != 0) + { + assert(to_stage->libs[i]->tls_sec_addr != 0x0); + memcpy((char *) base_stage_addr + + (uintptr_t) to_stage->libs_tls_sects->region_start + + (uintptr_t) tls_allocd, + (char *) lib_dep->data_base + + (uintptr_t) to_stage->libs[i]->tls_sec_off, + lib_dep->tls_sec_size); + tls_allocd += to_stage->libs[i]->tls_sec_size; + } + + munmap(lib_dep->data_base, lib_dep->data_size); + lib_dep->data_base = NULL; + lib_dep->data_size = 0; + } + + /* Copy over environ variables + * + * We need a pointer to an array of string pointers, so we synthetically + * create one. We don't expect this pointer to move, as the maximum allowed + * size for the `environ` array is already allocated + */ + + void *environ_addr + = (char *) to_stage->environ_ptr + (uintptr_t) base_stage_addr; + *((uintptr_t *) environ_addr) = sizeof(void *); + environ_addr = (char *) environ_addr + sizeof(char *); + + // Copy over prepared `environ` data from manager + memcpy(environ_addr, to_stage->cc->env_ptr, to_stage->cc->env_ptr_sz); + + to_stage->staged_addr = base_stage_addr; +} + /******************************************************************************* * Print functions ******************************************************************************/ static void print_lib_dep_seg(struct SegmentMap *lib_dep_seg) { - printf(">> bot %p // top %p // off 0x%zx // corr 0x%zx // msz 0x%zx // fsz " + printf(">> bot %p // off 0x%zx // msz 0x%zx // fsz " "0x%zx\n", - lib_dep_seg->mem_bot, lib_dep_seg->mem_top, lib_dep_seg->offset, - lib_dep_seg->correction, lib_dep_seg->mem_sz, lib_dep_seg->file_sz); + lib_dep_seg->mem_bot, lib_dep_seg->offset, lib_dep_seg->mem_sz, + lib_dep_seg->file_sz); } static void @@ -1328,3 +1230,17 @@ print_lib_dep(struct LibDependency *lib_dep) printf("- rela_maps_count : %zu\n", lib_dep->rela_maps_count); printf("== DONE\n"); } + +static void +print_comp_simple(struct Compartment *to_print) +{ + printf("== COMPARTMENT SIMPLE -- ID %zu\n", to_print->id); + printf("-- staged_addr : %p\n", to_print->staged_addr); + printf("-- total_size : %#zx\n", to_print->total_size); + printf("-- data_size: %#zx\n", to_print->data_size); + for (size_t i = 0; i < to_print->libs_count; ++i) + { + printf("\t* lib %zu `%s` >> %p\n", i, to_print->libs[i]->lib_name, + to_print->libs[i]->lib_mem_base); + } +} diff --git a/src/intercept.c b/src/intercept.c index ce28ecd..0b39c09 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -30,11 +30,13 @@ setup_intercepts() = cheri_address_set(cheri_pcc_get(), (uintptr_t) comp_exec_out); } -size_t -my_call_comp( - size_t comp_id, char *fn_name, void *args) // TODO , size_t args_count) -{ - struct Compartment *to_call = manager_get_compartment_by_id(comp_id); - return exec_comp(to_call, fn_name, args); - /*return exec_comp(to_call, fn_name, args, args_count);*/ -} +// TODO Reimplement this for inter-compartment function calls +// +/*size_t*/ +/*my_call_comp(*/ +/*size_t comp_id, char *fn_name, void *args) // TODO , size_t args_count)*/ +/*{*/ +/*struct Compartment *to_call = manager_get_compartment_by_id(comp_id);*/ +/*return exec_comp(to_call, fn_name, args);*/ +/*[>return exec_comp(to_call, fn_name, args, args_count);<]*/ +/*}*/ diff --git a/src/manager.c b/src/manager.c index 7b14f64..0246df4 100644 --- a/src/manager.c +++ b/src/manager.c @@ -18,6 +18,11 @@ void *__capability manager_ddc = 0; const char *comp_config_suffix = ".comp"; +// Constants for compartment environment setup. We allocate space for a maximum +// of 128 entries, with a maximum size of 128 bytes per entry. Numbers chosen +// aribtrarily. +// +// TODO consider better values for `avg_sz_per_env_entry` and `max_env_count` char **proc_env_ptr = NULL; size_t proc_env_ptr_sz = 0; unsigned short proc_env_count = 0; @@ -27,7 +32,12 @@ const size_t max_env_sz = max_env_count * sizeof(char *) + avg_sz_per_env_entry * max_env_count; extern char **environ; -// Functions +/******************************************************************************* + * Forward declarations + ******************************************************************************/ + +static void *get_next_comp_addr(size_t); +static void *__capability make_new_ddc(struct Compartment *, void *); static struct CompConfig * parse_compartment_config_file(char *, bool); @@ -46,22 +56,28 @@ prepare_compartment_environ(); static void * prepare_compartment_args(char **args, struct CompEntryPointDef); +static void * +comp_ptr_to_mapping_addr(void *, void *); + static struct Compartment * get_comp(struct Compartment *); // Printing -static void print_full_cap(uintcap_t); +static void +print_full_cap(void *__capability); static void pp_cap(void *__capability); static void print_comp(struct Compartment *); +static void +print_mapping_simple(struct CompMapping *); /******************************************************************************* * Utility functions ******************************************************************************/ static void -print_full_cap(uintcap_t cap) +print_full_cap(void *__capability cap) { uint32_t words[4]; // Hack to demonstrate! In real code, be more careful // about sizes, etc. @@ -87,21 +103,36 @@ pp_cap(void *__capability ptr) uint64_t offset = cheri_offset_get(ptr); - printf("Capability: %#lp\n", ptr); + printf("Capability: %#lx\n", (uintptr_t) ptr); printf("Tag: %d, Perms: %04lx, Type: %lx, Address: %04lx, Base: %04lx, " "End: %04lx, Flags: %lx, " "Length: %04lx, Offset: %04lx\n", tag, perms, type, address, base, base + length, flags, length, offset); } -void * -get_next_comp_addr(void) +static void * +get_next_comp_addr(size_t comp_sz) { if (min_next_comp_addr == NULL) { min_next_comp_addr = (void *) comp_start_addr; } - return min_next_comp_addr; + void *next_addr = min_next_comp_addr; + min_next_comp_addr = (char *) min_next_comp_addr + + align_up(comp_sz + comp_page_interval_count * sysconf(_SC_PAGESIZE), + sysconf(_SC_PAGESIZE)); + return next_addr; +} + +static void *__capability make_new_ddc( + struct Compartment *comp, void *target_addr) +{ + void *__capability new_ddc + = cheri_address_set(cheri_ddc_get(), (intptr_t) target_addr); + new_ddc = cheri_bounds_set(new_ddc, comp->total_size); + new_ddc + = cheri_offset_set(new_ddc, (uintptr_t) comp->scratch_mem_stack_top); + return new_ddc; } struct Compartment * @@ -114,46 +145,171 @@ register_new_comp(char *filename, bool allow_default_entry) struct CompConfig *new_cc = parse_compartment_config_file(filename, allow_default_entry); - new_cc->base_address = get_next_comp_addr(); new_cc->env_ptr = proc_env_ptr; new_cc->env_ptr_sz = proc_env_ptr_sz; new_cc->env_ptr_count = proc_env_count; struct Compartment *new_comp = comp_from_elf(filename, new_cc); new_comp->id = comps_count; - void *__capability new_comp_ddc - = cheri_address_set(cheri_ddc_get(), (intptr_t) new_comp->base); - new_comp_ddc = cheri_bounds_set( - new_comp_ddc, (char *) new_comp->mem_top - (char *) new_comp->base); - new_comp_ddc = cheri_offset_set(new_comp_ddc, - (char *) new_comp->scratch_mem_stack_top - (char *) new_comp->base); - new_comp->ddc = new_comp_ddc; comps_count += 1; comps = realloc(comps, comps_count * sizeof(struct Compartment *)); comps[comps_count - 1] = new_comp; - min_next_comp_addr = align_up((char *) comp_start_addr + new_comp->size - + comp_page_interval_count * sysconf(_SC_PAGESIZE), - sysconf(_SC_PAGESIZE)); - return new_comp; } +struct CompMapping * +mapping_new(struct Compartment *to_map) +{ + return mapping_new_fixed(to_map, NULL); +} + +struct CompMapping * +mapping_new_fixed(struct Compartment *to_map, void *addr) +{ + int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS; + if (addr != NULL) + { + assert((uintptr_t) addr % to_map->page_size == 0); + mmap_flags |= MAP_FIXED; + } + // Map new compartment + void *map_result = mmap(addr, to_map->total_size, + PROT_READ | PROT_WRITE | PROT_EXEC, mmap_flags, -1, 0); + if (map_result == MAP_FAILED) + { + err(1, "Error mapping compartment %zu data at addr %p", to_map->id, + addr); + } + addr = map_result; + + memcpy(addr, to_map->staged_addr, to_map->total_size); + + // Set appropriate `mprotect` flags + struct LibDependency *lib_dep; + struct SegmentMap lib_dep_seg; + for (size_t i = 0; i < to_map->libs_count; ++i) + { + lib_dep = to_map->libs[i]; + for (size_t j = 0; j < lib_dep->lib_segs_count; ++j) + { + lib_dep_seg = lib_dep->lib_segs[j]; + if (mprotect(get_seg_target(addr, lib_dep, j), lib_dep_seg.mem_sz, + lib_dep_seg.prot_flags) + != 0) + { + err(1, "Error setting permissions for %p (lib %zu seg %zu)", + get_seg_target(addr, lib_dep, j), i, j); + } + } + } + + // Update `environ` pointers + void *environ_addr = (char *) to_map->environ_ptr + (uintptr_t) addr; + *((char **) environ_addr) + = (char *) environ_addr + (uintptr_t) * ((char **) environ_addr); + + // Update the `environ` pointer with the mapping address + environ_addr = (char *) environ_addr + sizeof(void *); + + // We update all `environ` entries + for (unsigned short i = 0; i < to_map->cc->env_ptr_count; ++i) + { + *((char **) environ_addr + i) += (uintptr_t) environ_addr; + } + + // Perform relocations + struct LibRelaMapping *curr_rela_map; + for (size_t lib_idx = 0; lib_idx < to_map->libs_count; ++lib_idx) + { + for (size_t rela_idx = 0; + rela_idx < to_map->libs[lib_idx]->rela_maps_count; ++rela_idx) + { + curr_rela_map = &to_map->libs[lib_idx]->rela_maps[rela_idx]; + + if (!curr_rela_map->mapping_reloc) + { + continue; + } + *(void **) ((char *) curr_rela_map->rela_address + (uintptr_t) addr) + = (char *) curr_rela_map->target_func_address + + (uintptr_t) addr; + } + } + + struct CompMapping *new_mapping = malloc(sizeof(struct CompMapping)); + new_mapping->id = 0; // TODO + new_mapping->comp = to_map; + new_mapping->map_addr = addr; + new_mapping->ddc = make_new_ddc(to_map, addr); + + return new_mapping; +} + +void +mapping_free(struct CompMapping *to_unmap) +{ + int res; + + res = munmap(to_unmap->map_addr, to_unmap->comp->total_size); + if (res == -1) + { + err(1, "Error unmapping compartment %zu data at addr %p", to_unmap->id, + to_unmap->map_addr); + } + free(to_unmap); +} + +static void * +comp_ptr_to_mapping_addr(void *comp_ptr, void *mapping_addr) +{ + return (char *) comp_ptr + (uintptr_t) mapping_addr; +} + +/* Execute a mapped compartment, by jumping to the appropriate entry point. + * + * The entry point is given as a function name in the `fn_name` argument, and + * arguments to be passed are tightly packed in `args`. The requested entry + * point must have been registered prior during compartment initialization, by + * calling `parse_compartment_config`, and passing an appropriate `.comp` + * config file. + */ int64_t -exec_comp(struct Compartment *to_exec, char *entry_fn, char **entry_fn_args) +mapping_exec(struct CompMapping *to_exec, char *fn_name, char **fn_args_arr) { - struct CompEntryPointDef comp_entry - = get_entry_point(entry_fn, to_exec->cc); - void *comp_args = prepare_compartment_args(entry_fn_args, comp_entry); + struct CompConfig *to_exec_cc = to_exec->comp->cc; + struct CompEntryPointDef comp_entry = get_entry_point(fn_name, to_exec_cc); - struct Compartment *old_comp = loaded_comp; - loaded_comp = to_exec; - int64_t exec_res - = comp_exec(to_exec, entry_fn, comp_args, comp_entry.arg_count); - loaded_comp = old_comp; + // TODO remove + void *fn = NULL; + for (size_t i = 0; i < to_exec_cc->entry_point_count; ++i) + { + if (!strcmp(fn_name, to_exec_cc->entry_points[i].name)) + { + fn = (void *) ((char *) to_exec_cc->entry_points[i].comp_addr + + (uintptr_t) to_exec->map_addr); + break; + } + } + if (!fn) + { + errx(1, "Did not find entry point `%s`!\n", fn_name); + } - return exec_res; + void *fn_args = prepare_compartment_args(fn_args_arr, comp_entry); + assert(comp_entry.arg_count <= 3); // TODO currently hard limited by + // number of registers in + // `comp_exec_in` + void *comp_sp = comp_ptr_to_mapping_addr( + to_exec->comp->scratch_mem_stack_top, to_exec->map_addr); + void *comp_tls_region_start = comp_ptr_to_mapping_addr( + to_exec->comp->libs_tls_sects->region_start, to_exec->map_addr); + int64_t result + = comp_exec_in(comp_sp, to_exec->ddc, fn, fn_args, comp_entry.arg_count, + sealed_redirect_cap, (char *) comp_tls_region_start); + free(fn_args); + return result; } void @@ -189,37 +345,6 @@ get_comp(struct Compartment *to_find) errx(1, "Couldn't find requested compartment with id %zu.", to_find->id); } -struct Compartment * -manager_find_compartment_by_addr(void *addr) -{ - size_t i; - for (i = 0; i < comps_count; ++i) - { - if (comps[i]->base <= addr - && (void *) ((char *) comps[i]->base + comps[i]->size) > addr) - { - break; - } - } - assert(i != comps_count); - return comps[i]; -} - -struct Compartment * -manager_find_compartment_by_ddc(void *__capability ddc) -{ - size_t i; - for (i = 0; i < comps_count; ++i) - { - if (comps[i]->ddc == ddc) - { - return comps[i]; - } - } - // TODO improve error message with ddc - errx(1, "Could not find compartment."); -} - struct Compartment * manager_get_compartment_by_id(size_t id) { @@ -449,7 +574,6 @@ make_default_comp_config() cc->stack_size = DEFAULT_COMP_STACK_SZ; cc->entry_points = make_default_comp_entry_point(); cc->entry_point_count = 1; - cc->base_address = NULL; return cc; } @@ -458,18 +582,8 @@ print_comp(struct Compartment *to_print) { printf("== COMPARTMENT\n"); printf("- id : %lu\n", to_print->id); - { - printf("- DDC : "); - printf(" base - 0x%lx ", cheri_base_get(to_print->ddc)); - printf(" length - 0x%lx ", cheri_length_get(to_print->ddc)); - printf(" address - 0x%lx ", cheri_address_get(to_print->ddc)); - printf(" offset - 0x%lx ", cheri_offset_get(to_print->ddc)); - printf("\n"); - } - printf("- size : 0x%zx\n", to_print->size); - printf("- base : %p\n", to_print->base); - printf("- mem_top : %p\n", to_print->mem_top); - printf("- mapped : %s\n", to_print->mapped ? "true" : "false"); + printf("- total_size : 0x%zx\n", to_print->total_size); + printf("- data_size : 0x%zx\n", to_print->data_size); printf("- environ_ptr : %p\n", (void *) to_print->environ_ptr); printf("- environ_sz : 0x%zx\n", to_print->environ_sz); @@ -502,3 +616,19 @@ print_comp(struct Compartment *to_print) printf("== DONE\n"); } + +static void +print_mapping_simple(struct CompMapping *to_print) +{ + printf("== MAPPING SIMPLE -- ID %zu\n", to_print->id); + printf("-- map_addr : %p\n", to_print->map_addr); + printf("-- DDC : "); + print_full_cap(to_print->ddc); + printf("-- total_size : %#zx\n", to_print->comp->total_size); + for (size_t i = 0; i < to_print->comp->libs_count; ++i) + { + printf("\t* lib %zu `%s` >> %p\n", i, to_print->comp->libs[i]->lib_name, + (void *) ((char *) to_print->comp->libs[i]->lib_mem_base + + (uintptr_t) to_print->map_addr)); + } +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 82a5306..b90f879 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -137,6 +137,7 @@ endfunction() set(func_binaries "test_map" "test_map_multi" + #"test_args_near_unmapped" #"test_two_comps" #"test_two_comps_inter_call" @@ -159,6 +160,7 @@ set(comp_binaries "simple_malloc" "simple_malloc_saturate" "simple_open_write" + "simple_fprintf" "simple_printf" "simple_static_var" "simple_static_var-external" @@ -197,6 +199,7 @@ set(tests "simple_malloc" "simple_malloc_saturate" "simple_open_write" + "simple_fprintf" "simple_printf" "simple_static_var" "simple_syscall_getpid" @@ -209,13 +212,10 @@ set(tests "lua_simple" "lua_script" - "lua_suite_some" + #"lua_suite_some" "test_map" "test_map_multi" - #"test_args_near_unmapped" - #"test_two_comps" - #"test_two_comps_inter_call" "args-simple args_simple check_simple 40 2" "args-more args_simple check_simple 40 2 2 2" # Check additional arguments are ignored @@ -267,16 +267,6 @@ new_dependency(tls_check $) new_dependency(test_map $) new_dependency(lua_script ${CMAKE_CURRENT_SOURCE_DIR}/hello_world.lua) -#new_dependency(test_args_near_unmapped $) -#new_dependency(test_args_near_unmapped ${CMAKE_CURRENT_SOURCE_DIR}/args_simple.comp) - -#new_dependency(test_two_comps $) -#new_dependency(test_two_comps $) -#new_dependency(test_two_comps ${CMAKE_CURRENT_SOURCE_DIR}/test_two_comps-comp1.comp) - -#new_dependency(test_two_comps_inter_call $) -#new_dependency(test_two_comps_inter_call $) -#new_dependency(test_two_comps_inter_call ${CMAKE_CURRENT_SOURCE_DIR}/test_two_comps-comp1.comp) # Prepare tests foreach(test_t IN LISTS tests) diff --git a/tests/compartment_harness.c b/tests/compartment_harness.c index 285d195..983b38e 100644 --- a/tests/compartment_harness.c +++ b/tests/compartment_harness.c @@ -3,22 +3,94 @@ #define __capability +#include #include #define CHERI_COMP_LINUX +typedef uintptr_t uintcap_t; + +uint64_t +cheri_length_get(void *ptr) +{ + return (uint64_t) ptr; +} + +uint64_t +cheri_address_get(void *ptr) +{ + return (uint64_t) ptr; +} + +uint64_t +cheri_base_get(void *ptr) +{ + return (uint64_t) ptr; +} + +uint64_t +cheri_flags_get(void *ptr) +{ + return (uint64_t) ptr; +} + +uint64_t +cheri_perms_get(void *ptr) +{ + return (uint64_t) ptr; +} + +uint64_t +cheri_type_get(void *ptr) +{ + return (uint64_t) ptr; +} + +bool +cheri_tag_get(void *ptr) +{ + return ptr == 0x0; +} + +uint64_t +cheri_offset_get(void *ptr) +{ + return (uint64_t) ptr; +} + +void * +cheri_ddc_get() +{ + return 0x0; +} + +void * +cheri_address_set(void *ptr, intptr_t addr) +{ + void *_ptr = ptr; + return (void *) addr; +} + +void * +cheri_bounds_set(void *ptr, intptr_t addr) +{ + intptr_t _addr = addr; + return ptr; +} + +void * +cheri_offset_set(void *ptr, intptr_t addr) +{ + intptr_t _addr = addr; + return ptr; +} #include "../src/compartment.c" +#include "../src/manager.c" extern char **environ; char **proc_env_ptr; void *__capability sealed_redirect_cap = NULL; -// XXX Should be unused -const unsigned short avg_sz_per_env_entry = 128; -const unsigned short max_env_count = 128; -const size_t max_env_sz - = max_env_count * sizeof(char *) + avg_sz_per_env_entry * max_env_count; - int64_t comp_exec_in(void *comp_sp, void *__capability comp_ddc, void *fn, void *args, size_t args_count, void *__capability src, void *tls) @@ -31,7 +103,8 @@ comp_exec_in(void *comp_sp, void *__capability comp_ddc, void *fn, void *args, void *__capability _src = src; void *_tls = tls; - return (int64_t) fn; + int64_t res = ((int64_t(*)()) fn)(); + return res; } int @@ -43,26 +116,12 @@ main(int argc, char **argv) } char *file = argv[1]; - proc_env_ptr = environ; - - struct CompEntryPointDef *mock_cep - = malloc(sizeof(struct CompEntryPointDef)); - mock_cep->name = malloc(strlen("main") + 1); - strcpy((char *) mock_cep->name, "main"); - mock_cep->arg_count = 0; - mock_cep->args_type = NULL; - - struct CompConfig *mock_cc = malloc(sizeof(struct CompConfig)); - mock_cc->heap_size = 0x800000UL; - mock_cc->stack_size = 0x80000UL; - mock_cc->entry_points = mock_cep; - mock_cc->entry_point_count = 1; - mock_cc->base_address = (void *) 0x1000000UL; - - struct Compartment *hw_comp = comp_from_elf(file, mock_cc); + struct Compartment *hw_comp = register_new_comp(file, true); hw_comp->id = 0; - comp_map(hw_comp); + struct CompMapping *hw_map = mapping_new(hw_comp); + mapping_exec(hw_map, "main", NULL); + mapping_free(hw_map); comp_clean(hw_comp); return 0; } diff --git a/tests/manager_arg_passer.c b/tests/manager_arg_passer.c index ab6ecf0..afee8de 100644 --- a/tests/manager_arg_passer.c +++ b/tests/manager_arg_passer.c @@ -24,11 +24,12 @@ main(int argc, char **argv) char *file = argv[1]; struct Compartment *arg_comp = register_new_comp(file, false); - comp_map(arg_comp); + struct CompMapping *arg_map = mapping_new(arg_comp); char *entry_func = argv[2]; char **entry_func_args = &argv[3]; - int comp_result = exec_comp(arg_comp, argv[2], &argv[3]); + int comp_result = mapping_exec(arg_map, argv[2], &argv[3]); + mapping_free(arg_map); comp_clean(arg_comp); return comp_result; } diff --git a/tests/manager_caller.c b/tests/manager_caller.c index 6c7994a..be3734f 100644 --- a/tests/manager_caller.c +++ b/tests/manager_caller.c @@ -12,8 +12,9 @@ main(int argc, char **argv) char *file = argv[1]; struct Compartment *hw_comp = register_new_comp(file, true); - comp_map(hw_comp); - int comp_result = exec_comp(hw_comp, "main", NULL); + struct CompMapping *hw_map = mapping_new(hw_comp); + int comp_result = mapping_exec(hw_map, "main", NULL); + mapping_free(hw_map); comp_clean(hw_comp); return comp_result; } diff --git a/tests/manager_caller_multiple.c b/tests/manager_caller_multiple.c index c41583d..f97b53a 100644 --- a/tests/manager_caller_multiple.c +++ b/tests/manager_caller_multiple.c @@ -18,12 +18,13 @@ main(int argc, char **argv) char *file = argv[1]; struct Compartment *hw_comp = register_new_comp(file, true); + struct CompMapping *hw_map; int comp_result = 0; for (size_t i = 0; i < comps_count; ++i) { - comp_map(hw_comp); - comp_result = (exec_comp(hw_comp, "main", NULL) != 0) || comp_result; - comp_unmap(hw_comp); + hw_map = mapping_new(hw_comp); + comp_result = (mapping_exec(hw_map, "main", NULL) != 0) || comp_result; + mapping_free(hw_map); } comp_clean(hw_comp); assert(!comp_result); diff --git a/tests/simple_fprintf.c b/tests/simple_fprintf.c new file mode 100644 index 0000000..8e29a2c --- /dev/null +++ b/tests/simple_fprintf.c @@ -0,0 +1,12 @@ +#include +#include + +int +main(void) +{ + FILE *my_stdout = fdopen(STDOUT_FILENO, "w"); + const char *hw = "Hello World!"; + fprintf(my_stdout, "Inside - %s\n", hw); + fclose(my_stdout); + return 0; +} diff --git a/tests/simple_printf.c b/tests/simple_printf.c index a3159df..781d565 100644 --- a/tests/simple_printf.c +++ b/tests/simple_printf.c @@ -4,10 +4,7 @@ int main(void) { - FILE *my_stdout = fdopen(STDOUT_FILENO, "w"); - const char *hw = "Hello World!"; - fprintf(my_stdout, "Inside - %s\n", hw); - /*printf("Inside - %s\n", hw);*/ - fclose(my_stdout); + printf("Inside - Hello World\n"); + printf("Inside2 - Hello World\n"); return 0; } diff --git a/tests/test_map.c b/tests/test_map.c index 891821d..017f076 100644 --- a/tests/test_map.c +++ b/tests/test_map.c @@ -1,6 +1,8 @@ #include "compartment.c" #include "manager.h" +#include + int main() { @@ -9,7 +11,13 @@ main() char *file = "./simple.so"; struct Compartment *hw_comp = register_new_comp(file, true); - comp_map(hw_comp); + printf("REG DONE\n"); + struct CompMapping *hw_map = mapping_new(hw_comp); + printf("\tsz - %#zx\n", hw_comp->total_size); + printf("NEW DONE\n"); + mapping_free(hw_map); + printf("FREE DONE\n"); comp_clean(hw_comp); + printf("CLEAN DONE\n"); return 0; } diff --git a/tests/test_map_multi.c b/tests/test_map_multi.c index 75f4971..cafdd04 100644 --- a/tests/test_map_multi.c +++ b/tests/test_map_multi.c @@ -9,10 +9,12 @@ main() char *file = "./simple.so"; struct Compartment *hw_comp = register_new_comp(file, true); + struct CompMapping *hw_map; for (size_t i = 0; i < 100; ++i) { - comp_map(hw_comp); - comp_unmap(hw_comp); + hw_map = mapping_new(hw_comp); + mapping_exec(hw_map, "main", NULL); + mapping_free(hw_map); } comp_clean(hw_comp); return 0;