diff --git a/include/comp_utils.h b/include/comp_utils.h new file mode 100644 index 0000000..c230ae7 --- /dev/null +++ b/include/comp_utils.h @@ -0,0 +1,17 @@ +#ifndef _COMP_UTILS_H +#define _COMP_UTILS_H + +#include +#include +#include + +#include "cheriintrin.h" + +void *malloc(size_t); +void +free(void *); +void *calloc(size_t, size_t); +void * +realloc(void *, size_t); + +#endif // _COMP_UTILS_H diff --git a/include/compartment.h b/include/compartment.h index cd18d0e..f84e1a8 100644 --- a/include/compartment.h +++ b/include/compartment.h @@ -47,30 +47,12 @@ comp_exec_out(); extern void __clear_cache(void *, void *); -// Number of instructions to inject at intercepted function call point -// TODO ensure there is sufficient space for these, so we don't spill over -#define INTERCEPT_INSTR_COUNT 5 - // Number of instructions required by the transition function #define COMP_TRANS_FN_INSTR_CNT 4 extern void *__capability sealed_redirect_cap; extern void *__capability comp_return_caps[2]; -/* For a function to be intercepted, information required to insert the - * redirect code and perform redirection - * - * TODO recheck this is properly used, or re-design into a more light-weight - * approach with pre-given transition capabilities - */ -struct InterceptPatch -{ - int *patch_addr; - int32_t instr[INTERCEPT_INSTR_COUNT]; - uintptr_t comp_manager_cap_addr; - void *__capability manager_cap; -}; - // Maximum size of an argument, in bytes #define COMP_ARG_SIZE 8 @@ -210,10 +192,6 @@ struct Compartment // Hardware info - maybe move size_t page_size; - - // Misc - unsigned short curr_intercept_count; - struct InterceptPatch *intercept_patches; }; int @@ -221,9 +199,7 @@ entry_point_cmp(const void *, const void *); struct Compartment * comp_init(); struct Compartment * -comp_from_elf(char *, char **, size_t, char **, void **, size_t, void *); -void -comp_add_intercept(struct Compartment *, uintptr_t, uintptr_t); +comp_from_elf(char *, char **, size_t, void *); void comp_map(struct Compartment *); void diff --git a/include/intercept.h b/include/intercept.h index 70ce1db..83531f6 100644 --- a/include/intercept.h +++ b/include/intercept.h @@ -11,8 +11,6 @@ #include "cheriintrin.h" -#include "mem_mng.h" - // Forward declarations struct Compartment; extern struct Compartment *loaded_comp; @@ -21,6 +19,8 @@ exec_comp(struct Compartment *, char *, char **); struct Compartment *manager_get_compartment_by_id(size_t); extern void *__capability manager_ddc; +extern void +comp_exec_out(); // Number of capabilities required to perform a transition #define COMP_RETURN_CAPS_COUNT 2 @@ -55,43 +55,7 @@ intercept_wrapper(); void setup_intercepts(); -time_t -intercepted_time(time_t *); -FILE * -intercepted_fopen(const char *, const char *); -size_t -intercepted_fread(void *__restrict, size_t, size_t, FILE *__restrict); -size_t -intercepted_fwrite(void *__restrict, size_t, size_t, FILE *__restrict); -int -intercepted_fclose(FILE *); -int -intercepted_getc(FILE *); -int -intercepted_fputc(int, FILE *); -int -intercepted___srget(FILE *); - -void * -my_realloc(void *, size_t); -void *my_malloc(size_t); -void -my_free(void *); -int -my_fprintf(FILE *, const char *, ...); - size_t my_call_comp(size_t, char *, void *); -static const struct FuncIntercept to_intercept_funcs[] = { - /* Mem funcs */ - { "malloc", (void *) my_malloc, NULL }, - { "realloc", (void *) my_realloc, NULL }, - { "free", (void *) my_free, NULL }, -}; -// -// Functions to be intercepted and associated data -#define INTERCEPT_FUNC_COUNT \ - sizeof(to_intercept_funcs) / sizeof(to_intercept_funcs[0]) -extern struct FuncIntercept comp_intercept_funcs[INTERCEPT_FUNC_COUNT]; #endif // _INTERCEPT_H diff --git a/include/manager.h b/include/manager.h index 1cc4cbc..d00b182 100644 --- a/include/manager.h +++ b/include/manager.h @@ -83,6 +83,4 @@ clean_compartment_config(struct CompEntryPointDef *, size_t); * Memory allocation ******************************************************************************/ -#include "mem_mng.h" - #endif // _MANAGER_H diff --git a/include/mem_mng.h b/include/mem_mng.h deleted file mode 100644 index fb5d8b0..0000000 --- a/include/mem_mng.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef MEM_MNG_H -#define MEM_MNG_H - -#include -#include -#include -#include - -#include - -#include "compartment.h" - -// TODO consider single linked list -struct MemAlloc -{ - uintptr_t ptr; - size_t size; - - struct MemAlloc *prev_alloc; - struct MemAlloc *next_alloc; -}; - -extern size_t comp_mem_alloc; -extern size_t comp_mem_max; - -void * -manager_register_mem_alloc(struct Compartment *, size_t); -void -manager_insert_new_alloc(struct Compartment *, struct MemAlloc *); -size_t -manager_free_mem_alloc(struct Compartment *, void *); -struct MemAlloc * -get_alloc_struct_from_ptr(struct Compartment *, uintptr_t); - -#endif // MEM_MNG_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d9a9cf2..bbd58e3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,13 @@ # Compartment management library add_library(chcomp STATIC manager.c - mem_mng.c compartment.c intercept.c transition.S ) target_include_directories(chcomp PRIVATE ${INCLUDE_DIR} ${TOML_INCLUDE_DIR}) target_link_libraries(chcomp PRIVATE tomllib) + +add_library(computils SHARED + comp_utils.c) +target_include_directories(computils PRIVATE ${INCLUDE_DIR}) diff --git a/src/comp_utils.c b/src/comp_utils.c new file mode 100644 index 0000000..259f247 --- /dev/null +++ b/src/comp_utils.c @@ -0,0 +1,46 @@ +#include "comp_utils.h" + +static void *malloc_ptr; +static size_t heap_mem_left; + +void * +malloc(size_t to_alloc) +{ + if (!malloc_ptr) + { + void *__capability ddc = cheri_ddc_get(); + malloc_ptr = (char *) cheri_address_get(ddc); + heap_mem_left = cheri_length_get(ddc) - cheri_offset_get(ddc); + } + if (to_alloc > heap_mem_left) + { + errx(1, "Insufficient heap space left."); + } + void *to_ret = malloc_ptr; + memset(to_ret, 0, to_alloc); + malloc_ptr = (char *) malloc_ptr + to_alloc; + heap_mem_left -= to_alloc; + return to_ret; +} + +void +free(void *to_free) +{ + // TODO temp usage for bump allocator implementation to satisfy compiler + to_free = to_free; +} + +void * +calloc(size_t elem_count, size_t elem_size) +{ + return malloc(elem_count * elem_size); +} + +void * +realloc(void *to_realloc, size_t new_size) +{ + // TODO temp usage for bump allocator implementation to satisfy compiler + to_realloc = to_realloc; + + return malloc(new_size); +} diff --git a/src/compartment.c b/src/compartment.c index 3e13dbd..2257788 100644 --- a/src/compartment.c +++ b/src/compartment.c @@ -6,8 +6,6 @@ const char *libs_path_env_var = "COMP_LIBRARY_PATH"; * Forward declarations ******************************************************************************/ -static void -get_lib_name(struct LibDependency *, const char *); static struct LibDependency * parse_lib_file(char *, struct Compartment *); static void @@ -21,8 +19,6 @@ parse_lib_dynamic_deps(Elf64_Shdr *, Elf64_Ehdr *, int, struct LibDependency *); static void find_comp_entry_points(char **, size_t, struct Compartment *); static void -find_comp_intercepts(char **, void **, size_t, struct Compartment *); -static void resolve_rela_syms(struct Compartment *); static struct LibSymSearchResult find_lib_dep_sym_in_comp(const char *, struct Compartment *, unsigned short); @@ -87,9 +83,6 @@ comp_init() new_comp->page_size = sysconf(_SC_PAGESIZE); - new_comp->curr_intercept_count = 0; - new_comp->intercept_patches = NULL; - return new_comp; } @@ -108,7 +101,6 @@ entry_point_cmp(const void *val1, const void *val2) */ struct Compartment * comp_from_elf(char *filename, char **entry_points, size_t entry_point_count, - char **intercepts, void **intercept_addrs, size_t intercept_count, void *new_comp_base) { struct Compartment *new_comp = comp_init(); @@ -156,114 +148,11 @@ comp_from_elf(char *filename, char **entry_points, size_t entry_point_count, new_comp->mem_top = new_comp->scratch_mem_stack_top; find_comp_entry_points(entry_points, entry_point_count, new_comp); - find_comp_intercepts( - intercepts, intercept_addrs, intercept_count, new_comp); resolve_rela_syms(new_comp); return new_comp; } -/* For a given Compartment `new_comp`, an address `intercept_target` pointing - * to a function found within the compartment which we would like to intercept, - * and a `intercept_data` struct representing information to perform the - * intercept, synthesize and inject intructions at the call point of the - * `intercept_target`, in order to perform a transition out of the compartment - * to call the appropriate function with higher privileges. - */ -void -comp_add_intercept(struct Compartment *new_comp, uintptr_t intercept_target, - uintptr_t redirect_addr) -{ - // TODO check whether negative values break anything in all these generated - // functions - int32_t new_instrs[INTERCEPT_INSTR_COUNT]; - size_t new_instr_idx = 0; - const ptraddr_t comp_manager_cap_addr = (ptraddr_t) new_comp->manager_caps - + new_comp->active_manager_caps_count - * sizeof(void *__capability); // TODO - - const int32_t arm_function_target_register = 0b01010; // use `x10` for now - const int32_t arm_transition_target_register = 0b01011; // use `x11` for now - - // `x10` is used to hold the address of the manager function we want to - // execute after a jump out of the compartment - // TODO ideally we want 1 `movz` and 3 `movk`, to be able to access any - // address, but this is sufficient for now - // movz x0, $target_fn_addr:lo16 - // movk x0, $target_fn_addr:hi16 - assert(intercept_target < ((ptraddr_t) 1 << 32)); - const uint32_t arm_movz_instr_mask = 0b11010010100 << 21; - const uint32_t arm_movk_instr_mask = 0b11110010101 << 21; - const ptraddr_t target_address_lo16 = (redirect_addr & ((1 << 16) - 1)) - << 5; - const ptraddr_t target_address_hi16 = (redirect_addr >> 16) << 5; - const int32_t arm_movz_intr = arm_movz_instr_mask | target_address_lo16 - | arm_function_target_register; - const int32_t arm_movk_intr = arm_movk_instr_mask | target_address_hi16 - | arm_function_target_register; - new_instrs[new_instr_idx++] = arm_movz_intr; - new_instrs[new_instr_idx++] = arm_movk_intr; - - /* `ldpbr` instr generation */ - // TODO do we have space to insert these instructions? - // TODO what if we need to jump more than 4GB away? - // Use `adrp` to get address close to address of manager capability required - // adrp x11, $OFFSET - const uint32_t arm_adrp_instr_mask = 0b10010000 << 24; - const ptraddr_t target_address - = (comp_manager_cap_addr >> 12) - (intercept_target >> 12); - assert(target_address < ((ptraddr_t) 1 << 32)); - const int32_t arm_adrp_immlo = (target_address & 0b11) << 29; - const int32_t arm_adrp_immhi = (target_address >> 2) << 5; - const int32_t arm_adrp_instr = arm_adrp_instr_mask | arm_adrp_immlo - | arm_adrp_immhi | arm_transition_target_register; - new_instrs[new_instr_idx++] = arm_adrp_instr; - - // `ldr` capability within compartment pointing to manager capabilities - // ldr (unsigned offset, capability, normal base) - // `ldr c11, [x11, $OFFSET]` - const uint32_t arm_ldr_instr_mask = 0b1100001001 - << 22; // includes 0b00 bits for `op` field - ptraddr_t arm_ldr_pcc_offset - = comp_manager_cap_addr; // offset within 4KB page - ptraddr_t offset_correction = align_down(comp_manager_cap_addr, 1 << 12); - arm_ldr_pcc_offset -= offset_correction; - - assert(arm_ldr_pcc_offset < 65520); // from ISA documentation - assert(arm_ldr_pcc_offset % 16 == 0); - arm_ldr_pcc_offset = arm_ldr_pcc_offset << 10; - const int32_t arm_ldr_base_register = arm_transition_target_register - << 5; // use `x11` for now - const int32_t arm_ldr_dest_register - = arm_transition_target_register; // use `c11` for now - const int32_t arm_ldr_instr = arm_ldr_instr_mask | arm_ldr_pcc_offset - | arm_ldr_base_register | arm_ldr_dest_register; - new_instrs[new_instr_idx++] = arm_ldr_instr; - - // `b` instr generation - ptraddr_t arm_b_instr_offset - = (((uintptr_t) new_comp->mng_trans_fn) - - (intercept_target + new_instr_idx * sizeof(uint32_t))) - / 4; - assert(arm_b_instr_offset < (1 << 27)); - arm_b_instr_offset &= (1 << 26) - 1; - const uint32_t arm_b_instr_mask = 0b101 << 26; - uintptr_t arm_b_instr = arm_b_instr_mask | arm_b_instr_offset; - new_instrs[new_instr_idx++] = arm_b_instr; - - assert(new_instr_idx == INTERCEPT_INSTR_COUNT); - struct InterceptPatch new_patch; - new_patch.patch_addr = (void *) intercept_target; - memcpy(new_patch.instr, new_instrs, sizeof(new_instrs)); - __clear_cache(new_patch.instr, new_patch.instr + sizeof(new_instrs)); - new_patch.comp_manager_cap_addr = comp_manager_cap_addr; - new_patch.manager_cap = sealed_redirect_cap; - new_comp->curr_intercept_count += 1; - new_comp->intercept_patches = realloc(new_comp->intercept_patches, - new_comp->curr_intercept_count * sizeof(struct InterceptPatch)); - new_comp->intercept_patches[new_comp->curr_intercept_count - 1] = new_patch; -} - /* Map a struct Compartment into memory, making it ready for execution */ void @@ -324,20 +213,6 @@ comp_map(struct Compartment *to_map) err(1, "Error mapping compartment %zu stack!\n", to_map->id); } - // Inject intercept instructions within identified intercepted functions - for (unsigned short i = 0; i < to_map->curr_intercept_count; ++i) - { - struct InterceptPatch to_patch = to_map->intercept_patches[i]; - // TODO change to memcpy? - for (size_t j = 0; j < INTERCEPT_INSTR_COUNT; ++j) - { - int32_t *curr_addr = to_patch.patch_addr + j; - *curr_addr = to_patch.instr[j]; - } - *((void *__capability *) to_patch.comp_manager_cap_addr) - = to_patch.manager_cap; - } - // Inject manager transfer function memcpy(to_map->mng_trans_fn, (void *) &compartment_transition_out, to_map->mng_trans_fn_sz); @@ -457,7 +332,10 @@ comp_clean(struct Compartment *to_clean) // Clean library relocation mappings for (j = 0; j < curr_lib_dep->rela_maps_count; ++j) { - free(curr_lib_dep->rela_maps[j].rela_name); + if (curr_lib_dep->rela_maps[j].rela_name) + { + free(curr_lib_dep->rela_maps[j].rela_name); + } } free(curr_lib_dep->rela_maps); @@ -467,7 +345,6 @@ comp_clean(struct Compartment *to_clean) } free(to_clean->libs); free(to_clean->entry_points); - free(to_clean->intercept_patches); free(to_clean); } @@ -491,7 +368,7 @@ parse_lib_file(char *lib_name, struct Compartment *new_comp) lib_fd = open(lib_path, O_RDONLY); if (lib_fd == -1) { - errx(1, "Error opening compartment file %s!\n", lib_path); + errx(1, "Error opening compartment file %s!\n", lib_name); } } @@ -507,16 +384,16 @@ parse_lib_file(char *lib_name, struct Compartment *new_comp) } struct LibDependency *new_lib = malloc(sizeof(struct LibDependency)); - new_lib->lib_name = malloc(strlen(lib_name)); + new_lib->lib_name = malloc(strlen(lib_name) + 1); strcpy(new_lib->lib_name, lib_name); if (lib_path) { - new_lib->lib_path = malloc(strlen(lib_path)); + new_lib->lib_path = malloc(strlen(lib_path) + 1); strcpy(new_lib->lib_path, lib_path); } else { - new_lib->lib_path = malloc(strlen(lib_name)); + new_lib->lib_path = malloc(strlen(lib_name) + 1); strcpy(new_lib->lib_path, lib_name); } @@ -686,10 +563,12 @@ parse_lib_symtb(Elf64_Shdr *symtb_shdr, Elf64_Ehdr *lib_ehdr, int lib_fd, for (size_t j = 0; j < lib_dep->lib_syms_count; ++j) { curr_sym = sym_tb[j]; - if (curr_sym.st_value == 0) + // TODO currently ignore symbols of unspecified type + if (ELF_ST_TYPE(curr_sym.st_info) == STT_NOTYPE) { continue; } + ld_syms[actual_syms].sym_offset = (void *) curr_sym.st_value; char *sym_name = &str_tb[curr_sym.st_name]; ld_syms[actual_syms].sym_name = malloc(strlen(sym_name) + 1); @@ -739,50 +618,55 @@ parse_lib_rela(Elf64_Shdr *rela_shdr, Elf64_Ehdr *lib_ehdr, int lib_fd, { curr_rela = rela_sec[j]; size_t curr_rela_sym_idx = ELF64_R_SYM(curr_rela.r_info); - Elf64_Sym curr_rela_sym = dyn_sym_tbl[curr_rela_sym_idx]; - if (curr_rela_sym_idx == 0) - { - // TODO In some test programs, there are some relocations with no - // name and some weird value; we currently filter them out, but - // they might mean something in the future - continue; - } - // Filter out some `libc` symbols we don't want to handle - // TODO at least right now - if (!strcmp(&dyn_str_tbl[curr_rela_sym.st_name], "environ")) + struct LibRelaMapping lrm = { NULL, 0x0, 0x0, -1, -1 }; + if (curr_rela_sym_idx != 0) { - warnx("Currently not relocating symbol `environ` from library %s - " - "using within a container might cause a crash.", - lib_dep->lib_name); - continue; + Elf64_Sym curr_rela_sym = dyn_sym_tbl[curr_rela_sym_idx]; + + // Filter out some `libc` symbols we don't want to handle + // TODO at least right now + if (!strcmp(&dyn_str_tbl[curr_rela_sym.st_name], "environ")) + { + warnx("Currently not relocating symbol `environ` from library " + "%s - " + "using within a container might cause a crash.", + lib_dep->lib_name); + continue; + } + else if (!strcmp(&dyn_str_tbl[curr_rela_sym.st_name], "__progname")) + { + warnx("Currently not relocating symbol `__progname` from " + "library %s " + "- using within a container might cause a crash.", + lib_dep->lib_name); + continue; + } + + lrm.rela_name + = malloc(strlen(&dyn_str_tbl[curr_rela_sym.st_name]) + 1); + strcpy(lrm.rela_name, &dyn_str_tbl[curr_rela_sym.st_name]); + lrm.rela_sym_type = ELF64_ST_TYPE(curr_rela_sym.st_info); + lrm.rela_sym_bind = ELF64_ST_BIND(curr_rela_sym.st_info); + if (curr_rela_sym.st_value != 0) + { + new_relas[actual_relas].target_func_address + = curr_rela_sym.st_value + (char *) lib_dep->lib_mem_base; + } + // TODO + assert(curr_rela.r_addend == 0 + && "I want to check if we have symbol-related relocations with " + "addends"); } - else if (!strcmp(&dyn_str_tbl[curr_rela_sym.st_name], "__progname")) + else { - warnx( - "Currently not relocating symbol `__progname` from library %s " - "- using within a container might cause a crash.", - lib_dep->lib_name); - continue; + lrm.target_func_address + = curr_rela.r_addend + (char *) lib_dep->lib_mem_base; } - char *curr_rela_name - = malloc(strlen(&dyn_str_tbl[curr_rela_sym.st_name]) + 1); - strcpy(curr_rela_name, &dyn_str_tbl[curr_rela_sym.st_name]); - struct LibRelaMapping lrm; - - // TODO haven't handled addends on relocations yet - assert(curr_rela.r_addend == 0); + lrm.rela_address = curr_rela.r_offset + (char *) lib_dep->lib_mem_base; + memcpy(new_relas + actual_relas, &lrm, sizeof(struct LibRelaMapping)); - new_relas[actual_relas] = (struct LibRelaMapping) { curr_rela_name, - curr_rela.r_offset + (char *) lib_dep->lib_mem_base, NULL, - ELF64_ST_TYPE(curr_rela_sym.st_info), - ELF64_ST_BIND(curr_rela_sym.st_info) }; - if (curr_rela_sym.st_value != 0) - { - new_relas[actual_relas].target_func_address - = curr_rela_sym.st_value + (char *) lib_dep->lib_mem_base; - } actual_relas += 1; } lib_dep->rela_maps = realloc(lib_dep->rela_maps, @@ -819,7 +703,7 @@ parse_lib_dynamic_deps(Elf64_Shdr *dynamic_shdr, Elf64_Ehdr *lib_ehdr, lib_dep->lib_dep_names = realloc(lib_dep->lib_dep_names, (lib_dep->lib_dep_count + 1) * sizeof(char *)); lib_dep->lib_dep_names[lib_dep->lib_dep_count] - = malloc(strlen(&dynstr_tbl[dyn_entries[i].d_un.d_val])); + = malloc(strlen(&dynstr_tbl[dyn_entries[i].d_un.d_val]) + 1); strcpy(lib_dep->lib_dep_names[lib_dep->lib_dep_count], &dynstr_tbl[dyn_entries[i].d_un.d_val]); lib_dep->lib_dep_count += 1; @@ -851,39 +735,6 @@ find_comp_entry_points( } } -static void -find_comp_intercepts(char **intercepts, void **intercept_addrs, - size_t intercept_count, struct Compartment *new_comp) -{ - // Find symbols for intercepts - char **intercept_names = malloc(intercept_count * sizeof(char *)); - const char *so_plt_suffix = "@plt"; - for (size_t i = 0; i < intercept_count; ++i) - { - size_t to_intercept_name_len - = strlen(intercepts[i]) + strlen(so_plt_suffix) + 1; - intercept_names[i] = malloc(to_intercept_name_len); - strcpy(intercept_names[i], intercepts[i]); - strcat(intercept_names[i], so_plt_suffix); - } - for (size_t i = 0; i < intercept_count; ++i) - { - struct LibSymSearchResult found_sym - = find_lib_dep_sym_in_comp(intercept_names[i], new_comp, STT_FUNC); - if (found_sym.lib_idx == USHRT_MAX) - { - continue; - } - - // TODO double check - comp_add_intercept(new_comp, - (uintptr_t) extract_sym_offset(new_comp, found_sym), - (uintptr_t) intercept_addrs[i]); - free(intercept_names[i]); - } - free(intercept_names); -} - static void resolve_rela_syms(struct Compartment *new_comp) { @@ -943,14 +794,6 @@ do_pread(int fd, void *buf, size_t count, off_t offset) return res; } -static void -get_lib_name(struct LibDependency *lib_dep, const char *lib_path) -{ - const char *basename = strrchr(lib_path, '/') + 1; - lib_dep->lib_name = malloc(strlen(basename)); - strcpy(lib_dep->lib_name, basename); -} - static void * extract_sym_offset(struct Compartment *comp, struct LibSymSearchResult res) { @@ -969,7 +812,8 @@ find_lib_dep_sym_in_comp(const char *to_find, if (comp_to_search->libs[i]->lib_syms[j].sym_bind != STB_LOCAL && !strcmp( to_find, comp_to_search->libs[i]->lib_syms[j].sym_name) - && comp_to_search->libs[i]->lib_syms[j].sym_type == sym_type) + && comp_to_search->libs[i]->lib_syms[j].sym_type == sym_type + && comp_to_search->libs[i]->lib_syms[j].sym_offset != 0) { struct LibSymSearchResult res = { i, j }; return res; diff --git a/src/intercept.c b/src/intercept.c index 1613a36..ce28ecd 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -1,6 +1,5 @@ #include "intercept.h" -struct FuncIntercept comp_intercept_funcs[INTERCEPT_FUNC_COUNT]; void *__capability comp_return_caps[COMP_RETURN_CAPS_COUNT]; void *__capability sealed_redirect_cap; @@ -20,15 +19,6 @@ void *__capability sealed_redirect_cap; void setup_intercepts() { - for (size_t i = 0; - i < sizeof(to_intercept_funcs) / sizeof(to_intercept_funcs[0]); ++i) - { - comp_intercept_funcs[i].func_name = to_intercept_funcs[i].func_name; - comp_intercept_funcs[i].redirect_func - = to_intercept_funcs[i].redirect_func; - comp_intercept_funcs[i].intercept_pcc - = cheri_address_set(cheri_pcc_get(), (uintptr_t) intercept_wrapper); - } sealed_redirect_cap = manager_ddc; sealed_redirect_cap = cheri_address_set(sealed_redirect_cap, (intptr_t) comp_return_caps); @@ -40,64 +30,6 @@ setup_intercepts() = cheri_address_set(cheri_pcc_get(), (uintptr_t) comp_exec_out); } -/******************************************************************************* - * Intercept functions - * - * These functions are meant to be executed within a manager context, by - * intercepting certain functions within compartments which must have higher - * privlige - ******************************************************************************/ - -void * -my_realloc(void *ptr, size_t to_alloc) -{ - // TODO revisit this logic; do we keep a pointer in the manager of the - // currently loaded compartment (would probably require this to be set in - // the transition function), or do we get this information from the - // intercept source (could check the compartment mapping to see which - // compartment the source address comes from) - /*struct Compartment* comp = - * manager_find_compartment_by_ddc(cheri_ddc_get());*/ - struct Compartment *comp = loaded_comp; - - if (ptr == NULL) - { - return my_malloc(to_alloc); // TODO - } - - void *new_ptr = manager_register_mem_alloc(comp, to_alloc); - struct MemAlloc *old_alloc - = get_alloc_struct_from_ptr(comp, (uintptr_t) ptr); - memcpy( - new_ptr, ptr, to_alloc < old_alloc->size ? to_alloc : old_alloc->size); - manager_free_mem_alloc(comp, ptr); - return new_ptr; -} - -void * -my_malloc(size_t to_alloc) -{ - /*struct Compartment* comp = - * manager_find_compartment_by_ddc(cheri_ddc_get());*/ - struct Compartment *comp = loaded_comp; - assert(comp->scratch_mem_alloc + to_alloc < comp->scratch_mem_size); - void *new_mem = manager_register_mem_alloc(comp, to_alloc); - return new_mem; -} - -void -my_free(void *ptr) -{ - if (ptr == NULL) - { - return; - } - /*struct Compartment* comp = - * manager_find_compartment_by_ddc(cheri_ddc_get());*/ - manager_free_mem_alloc(loaded_comp, ptr); // TODO - return; -} - size_t my_call_comp( size_t comp_id, char *fn_name, void *args) // TODO , size_t args_count) diff --git a/src/manager.c b/src/manager.c index 01d4f60..b58d013 100644 --- a/src/manager.c +++ b/src/manager.c @@ -69,24 +69,15 @@ register_new_comp(char *filename, bool allow_default_entry) strcpy(ep_names[i], new_cep[i].name); } - char **intercept_names = calloc(INTERCEPT_FUNC_COUNT, sizeof(char *)); - void **intercept_addrs = calloc(INTERCEPT_FUNC_COUNT, sizeof(uintptr_t)); - for (size_t i = 0; i < INTERCEPT_FUNC_COUNT; ++i) - { - intercept_names[i] = malloc(strlen(comp_intercept_funcs[i].func_name)); - strcpy(intercept_names[i], comp_intercept_funcs[i].func_name); - intercept_addrs[i] = comp_intercept_funcs[i].redirect_func; - } - - struct Compartment *new_comp - = comp_from_elf(filename, ep_names, new_comp_ep_count, intercept_names, - intercept_addrs, INTERCEPT_FUNC_COUNT, get_next_comp_addr()); + struct Compartment *new_comp = comp_from_elf( + filename, ep_names, new_comp_ep_count, get_next_comp_addr()); new_comp->id = comps_count; void *__capability new_comp_ddc = cheri_address_set(cheri_ddc_get(), (uintptr_t) new_comp->base); - // TODO double check second parameter of `cheri_bounds_set` - new_comp_ddc = cheri_bounds_set( - new_comp_ddc, (uintptr_t) new_comp->scratch_mem_stack_top); + new_comp_ddc = cheri_bounds_set(new_comp_ddc, + (char *) new_comp->scratch_mem_stack_top - (char *) new_comp->base); + new_comp_ddc = cheri_offset_set(new_comp_ddc, + (char *) new_comp->scratch_mem_base - (char *) new_comp->base); new_comp->ddc = new_comp_ddc; struct CompWithEntries *new_cwe = malloc(sizeof(struct CompWithEntries)); @@ -105,12 +96,6 @@ register_new_comp(char *filename, bool allow_default_entry) free(ep_names[i]); } free(ep_names); - for (size_t i = 0; i < INTERCEPT_FUNC_COUNT; ++i) - { - free(intercept_names[i]); - } - free(intercept_names); - free(intercept_addrs); return new_comp; } diff --git a/src/mem_mng.c b/src/mem_mng.c deleted file mode 100644 index 061210d..0000000 --- a/src/mem_mng.c +++ /dev/null @@ -1,115 +0,0 @@ -#include "mem_mng.h" - -// MEM TODO - -/* An initial design of a simple bump allocator. This is here more to have - * something intercept `malloc` calls from the compartment, and might be - * scrapped in favour of something useful. The only requirement is that we are - * able to restrict what area of the memory we want to manage to the - * compartment scratch memory space - */ - -void * -manager_register_mem_alloc(struct Compartment *comp, size_t mem_size) -{ - // TODO better algorithm to find blocks of memory available for mapping - void *new_mem = (char *) comp->scratch_mem_base + comp->scratch_mem_alloc; - struct MemAlloc *new_alloc = malloc(sizeof(struct MemAlloc)); - new_alloc->ptr = (uintptr_t) new_mem; - new_alloc->size = mem_size; - manager_insert_new_alloc(comp, new_alloc); - comp->scratch_mem_alloc += __builtin_align_up(mem_size, sizeof(void *)); - return new_mem; -} - -void -manager_insert_new_alloc(struct Compartment *comp, struct MemAlloc *to_insert) -{ - if (comp->alloc_head == NULL) - { - to_insert->prev_alloc = NULL; - to_insert->next_alloc = NULL; - comp->alloc_head = to_insert; - return; - } - - if (comp->alloc_head->ptr > to_insert->ptr) - { - to_insert->next_alloc = comp->alloc_head; - to_insert->prev_alloc = NULL; - comp->alloc_head->prev_alloc = to_insert; - comp->alloc_head = to_insert; - return; - } - - struct MemAlloc *curr_alloc = comp->alloc_head; - while (curr_alloc->next_alloc != NULL && curr_alloc->ptr < to_insert->ptr) - { - curr_alloc = curr_alloc->next_alloc; - } - if (curr_alloc->next_alloc == NULL) - { - to_insert->prev_alloc = curr_alloc; - curr_alloc->next_alloc = to_insert; - to_insert->next_alloc = NULL; - return; - } - - to_insert->next_alloc = curr_alloc->next_alloc; - to_insert->next_alloc->prev_alloc = to_insert; - curr_alloc->next_alloc = to_insert; - to_insert->prev_alloc = curr_alloc; - return; -} - -size_t -manager_free_mem_alloc(struct Compartment *comp, void *ptr) -{ - struct MemAlloc *curr_alloc = comp->alloc_head; - while (curr_alloc != NULL && curr_alloc->ptr != (uintptr_t) ptr) - { - curr_alloc = curr_alloc->next_alloc; - } - - assert(curr_alloc != NULL && "Memory allocation not found to be freed."); - if (curr_alloc->prev_alloc != NULL) - { - curr_alloc->prev_alloc->next_alloc = curr_alloc->next_alloc; - } - if (curr_alloc->next_alloc != NULL) - { - curr_alloc->next_alloc->prev_alloc = curr_alloc->prev_alloc; - } - size_t to_return = curr_alloc->size; - free(curr_alloc); - - return to_return; -} - -/** - * Find allocation record in a compartment for a given address - * - * Given a compartment and an address, iterates over the memory allocations - * recorded for that compartment in order to find the allocation record - * refering to the given address. - * This currently expects the allocation record to exactly point to a given - * address to be searched, due to how the memory allocator is designed. - * - * \param comp Compartment in which we expect the allocation to exist - * \param ptr Address to search for - * \return A record indicating the requested memory allocation - */ -struct MemAlloc * -get_alloc_struct_from_ptr(struct Compartment *comp, uintptr_t ptr) -{ - struct MemAlloc *curr_alloc = comp->alloc_head; - while (curr_alloc->next_alloc != NULL) - { - if (curr_alloc->ptr == ptr) - { - return curr_alloc; - } - curr_alloc = curr_alloc->next_alloc; - } - errx(1, "ERROR: Could not find allocated pointer %Pu!\n", ptr); -} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c7c117c..1fa35d7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -57,7 +57,7 @@ function(new_comp_test test_name) add_library(${test_name} SHARED ${test_name}.c) set_target_properties(${test_name} PROPERTIES PREFIX "") - target_link_libraries(${test_name} PRIVATE chcomp lualib dl m) + target_link_libraries(${test_name} PRIVATE chcomp computils lualib dl m) target_include_directories(${test_name} PRIVATE ${INCLUDE_DIR} ${LUA_INCLUDE_DIR}) set_property(TARGET ${test_name} PROPERTY compartment TRUE) @@ -127,14 +127,17 @@ set(comp_binaries "simple_call_external" "simple_static_var" "simple_static_var-external" + "simple_global_var" + "simple_global_var-external" "simple_external" "simple_syscall_getpid" "simple_syscall_write" "simple_va_args" + "simple_open_write" "simple_fputs" - "simple_printf" "simple_fopen" - #"time" + "simple_malloc" + "time" #"lua_simple" #"lua_script" "args_simple" @@ -150,13 +153,15 @@ set(tests "simple_call_internal_weak" "simple_call_external" "simple_static_var" + "simple_global_var" "simple_syscall_getpid" "simple_syscall_write" "simple_va_args" - #"simple_fputs" - #"simple_printf" + "simple_open_write" + "simple_fputs" "simple_fopen" - #"time" + "simple_malloc" + "time" #"lua_simple" #"lua_script" "test_map" @@ -196,6 +201,9 @@ new_dependency(simple_call_external $) target_link_libraries(simple_static_var PRIVATE simple_static_var-external) new_dependency(simple_static_var $) +target_link_libraries(simple_global_var PRIVATE simple_global_var-external) +new_dependency(simple_global_var $) + #new_dependency(test_map $) #new_dependency(lua_script ${CMAKE_CURRENT_SOURCE_DIR}/hello_world.lua) diff --git a/tests/init_test.py b/tests/init_test.py index 4cf409d..c14cc00 100755 --- a/tests/init_test.py +++ b/tests/init_test.py @@ -16,6 +16,7 @@ LOCAL_LIBS = [ "./third-party/lua/liblua.so", + "./build/src/libcomputils.so" ] REMOTE_LIBS = [ "/lib/libc.so.7", diff --git a/tests/simple_fopen.c b/tests/simple_fopen.c index 7fd58d0..6409763 100644 --- a/tests/simple_fopen.c +++ b/tests/simple_fopen.c @@ -2,37 +2,50 @@ #include #include #include +#include #include void by_fopen() { FILE *fd = fopen("tmp", "w"); - fprintf(fd, "Hi\n"); + if (!fd) + { + err(1, "Error in fopen: "); + } fclose(fd); } void by_syscall() { + int fd = syscall(SYS_open, "tmp", O_CREAT); // open + if (fd == -1) + { + err(1, "Error in open: "); + } + syscall(SYS_close, fd); // close } void by_open() { - int fd = open("tmp", O_WRONLY | O_CREAT); + int fd = open("tmp", O_CREAT); if (fd == -1) { err(1, "Error in open: "); } - char *buf = "Hi\n"; - write(fd, buf, strlen(buf)); close(fd); } int main() { + write(STDOUT_FILENO, "== By open\n", 11); by_open(); + write(STDOUT_FILENO, "== By syscall\n", 14); + by_syscall(); + write(STDOUT_FILENO, "== By fopen\n", 12); + by_fopen(); return 0; } diff --git a/tests/simple_global_var-external.c b/tests/simple_global_var-external.c new file mode 100644 index 0000000..ccdf715 --- /dev/null +++ b/tests/simple_global_var-external.c @@ -0,0 +1,11 @@ +static int ext_val; + +int +get_ext_val() +{ + if (!ext_val) + { + ext_val = 42; + } + return ext_val; +} diff --git a/tests/simple_global_var.c b/tests/simple_global_var.c new file mode 100644 index 0000000..bb91272 --- /dev/null +++ b/tests/simple_global_var.c @@ -0,0 +1,12 @@ +#include + +int +get_ext_val(); + +int +main(void) +{ + int ext_val = get_ext_val(); + assert(ext_val == 42); + return 0; +} diff --git a/tests/simple_open_write.c b/tests/simple_open_write.c new file mode 100644 index 0000000..b68161b --- /dev/null +++ b/tests/simple_open_write.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include + +int +main(void) +{ + char *buf = "Hello File!\n"; + char *file = "out_syscall_write"; + int fd = open(file, O_WRONLY | O_CREAT); + if (fd == -1) + { + err(1, "Error in open: "); + } + if (write(fd, buf, strlen(buf)) == -1) + { + err(1, "Error in write: "); + } + if (close(fd) == -1) + { + err(1, "Error in close: "); + } + return 0; +} diff --git a/tests/simple_syscall_getpid.c b/tests/simple_syscall_getpid.c index 4956dfa..3bae87e 100644 --- a/tests/simple_syscall_getpid.c +++ b/tests/simple_syscall_getpid.c @@ -1,10 +1,11 @@ #include +#include #include int main(void) { - long int sc_pid = syscall(20); + long int sc_pid = syscall(SYS_getpid); pid_t pid = getpid(); assert(pid == sc_pid); return 0; diff --git a/tests/simple_syscall_write.c b/tests/simple_syscall_write.c index 119cd45..44d35f2 100644 --- a/tests/simple_syscall_write.c +++ b/tests/simple_syscall_write.c @@ -1,12 +1,13 @@ #include #include +#include #include int main(void) { char *buf = "Hello World!\n"; - long int sc_write = syscall(4, STDOUT_FILENO, buf, strlen(buf)); + long int sc_write = syscall(SYS_write, STDOUT_FILENO, buf, strlen(buf)); if (sc_write == -1) { err(1, "Error calling `syscall`:"); diff --git a/tests/simple_various.c b/tests/simple_various.c index 7d61a27..c3dc960 100644 --- a/tests/simple_various.c +++ b/tests/simple_various.c @@ -1,3 +1,4 @@ +#include #include #include @@ -12,7 +13,7 @@ do_print(const char *const to_print) int main(void) { - char *x = malloc(strlen(hw)); + char *x = malloc(strlen(hw) + 1); strcpy(x, hw); do_print(x); free(x);