diff --git a/include/compartment.h b/include/compartment.h index a453b19..8a70438 100644 --- a/include/compartment.h +++ b/include/compartment.h @@ -60,13 +60,9 @@ extern void *__capability comp_return_caps[2]; #error Expecting 64-bit Arm Morello platform #endif -/* Struct representing a valid entry point to a compartment - */ -struct CompEntryPoint -{ - const char *fn_name; - void *fn_addr; -}; +// Default sizes for compartment heap and stack, if not explicitly given +#define DEFAULT_COMP_HEAP_SZ 0x800000UL // 800kB +#define DEFAULT_COMP_STACK_SZ 0x80000UL // 80kB /* Struct representing one segment of an ELF binary. * @@ -169,14 +165,38 @@ struct TLSDesc unsigned short libs_count; }; +/* Struct representing configuration data for one entry point; this is just + * information that we expect to appear in the compartment, as given by its + * compartment configuration file + */ +struct CompEntryPointDef +{ + char *name; + size_t arg_count; + char **args_type; + void *comp_addr; +}; + +/* Struct representing a compartment configuration. + */ +struct CompConfig +{ + size_t heap_size; + size_t stack_size; + struct CompEntryPointDef *entry_points; + size_t entry_point_count; + void *base_address; +}; + /** * Struct representing ELF data necessary to load and eventually execute a * compartment */ struct Compartment { - // Identifiers + // Identifiers, manager by `manager.c` size_t id; + struct CompConfig *cc; // Execution info void *__capability ddc; // ELF data @@ -201,8 +221,6 @@ struct Compartment // Internal libraries and relocations size_t libs_count; struct LibDependency **libs; - size_t entry_point_count; - struct CompEntryPoint *entry_points; void *tls_lookup_func; size_t total_tls_size; struct TLSDesc *libs_tls_sects; @@ -216,7 +234,7 @@ entry_point_cmp(const void *, const void *); struct Compartment * comp_init(); struct Compartment * -comp_from_elf(char *, char **, size_t, void *); +comp_from_elf(char *, struct CompConfig *); // char **, size_t, void *); void comp_map(struct Compartment *); void diff --git a/include/manager.h b/include/manager.h index 01dfafb..d9762e2 100644 --- a/include/manager.h +++ b/include/manager.h @@ -21,7 +21,7 @@ #define align_up(x, align) __builtin_align_up(x, align) extern void *__capability manager_ddc; -extern struct CompWithEntries **comps; +extern struct Compartment **comps; extern struct Compartment *loaded_comp; /******************************************************************************* @@ -31,23 +31,6 @@ extern struct Compartment *loaded_comp; // Compartment configuration file suffix extern const char *comp_config_suffix; -/* Struct representing configuration data for one entry point; this is just - * information that we expect to appear in the compartment, as given by its - * compartment configuration file - */ -struct CompEntryPointDef -{ - const char *name; - size_t arg_count; - char **args_type; -}; - -struct CompWithEntries -{ - struct Compartment *comp; - struct CompEntryPointDef *cep; -}; - void * get_next_comp_addr(void); struct Compartment * diff --git a/src/compartment.c b/src/compartment.c index e460eee..45bbd4e 100644 --- a/src/compartment.c +++ b/src/compartment.c @@ -23,7 +23,7 @@ parse_lib_rela(Elf64_Shdr *, Elf64_Ehdr *, int, struct LibDependency *); static void parse_lib_dynamic_deps(Elf64_Shdr *, Elf64_Ehdr *, int, struct LibDependency *); static void -find_comp_entry_points(char **, size_t, struct Compartment *); +map_comp_entry_points(struct Compartment *); static void resolve_rela_syms(struct Compartment *); static struct LibSymSearchResult @@ -86,8 +86,6 @@ comp_init() new_comp->libs_count = 0; new_comp->libs = NULL; - new_comp->entry_point_count = 0; - new_comp->entry_points = NULL; new_comp->libs_tls_sects = NULL; new_comp->page_size = sysconf(_SC_PAGESIZE); @@ -95,26 +93,16 @@ comp_init() return new_comp; } -/* Comparison function for `struct CompEntryPoint` - */ -int -entry_point_cmp(const void *val1, const void *val2) -{ - struct CompEntryPoint *ep1 = *(struct CompEntryPoint **) val1; - struct CompEntryPoint *ep2 = *(struct CompEntryPoint **) val2; - return strcmp(ep1->fn_name, ep2->fn_name); -} - /* Give a binary ELF file in `filename`, read the ELF data and store it within * a `struct Compartment`. At this point, we only read data. */ struct Compartment * -comp_from_elf(char *filename, char **entry_points, size_t entry_point_count, - void *new_comp_base) +comp_from_elf(char *filename, struct CompConfig *cc) { struct Compartment *new_comp = comp_init(); - new_comp->base = new_comp_base; - new_comp->mem_top = new_comp_base; + 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; @@ -166,12 +154,12 @@ comp_from_elf(char *filename, char **entry_points, size_t entry_point_count, } free(libs_to_parse); - assert(entry_points); - assert(entry_point_count > 0); + assert(cc->entry_points); + assert(cc->entry_point_count > 0); init_comp_scratch_mem(new_comp); setup_environ(new_comp); - find_comp_entry_points(entry_points, entry_point_count, new_comp); + map_comp_entry_points(new_comp); resolve_comp_tls_regions(new_comp); resolve_rela_syms(new_comp); @@ -253,11 +241,11 @@ comp_map(struct Compartment *to_map) } /* 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 - */ + * + * 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; @@ -328,11 +316,11 @@ comp_exec( to_exec->mapped && "Attempting to execute an unmapped compartment.\n"); void *fn = NULL; - for (size_t i = 0; i < to_exec->entry_point_count; ++i) + for (size_t i = 0; i < to_exec->cc->entry_point_count; ++i) { - if (!strcmp(fn_name, to_exec->entry_points[i].fn_name)) + if (!strcmp(fn_name, to_exec->cc->entry_points[i].name)) { - fn = (void *) to_exec->entry_points[i].fn_addr; + fn = (void *) to_exec->cc->entry_points[i].comp_addr; break; } } @@ -414,8 +402,20 @@ comp_clean(struct Compartment *to_clean) free(curr_lib_dep->lib_path); free(curr_lib_dep); } + struct CompEntryPointDef curr_cep; + for (size_t i = 0; i < to_clean->cc->entry_point_count; ++i) + { + curr_cep = to_clean->cc->entry_points[i]; + for (size_t j = 0; j < curr_cep.arg_count; ++j) + { + free(curr_cep.args_type[j]); + } + free(curr_cep.args_type); + free(curr_cep.name); + } + free(to_clean->cc->entry_points); + free(to_clean->cc); free(to_clean->libs); - free(to_clean->entry_points); if (to_clean->libs_tls_sects) { free(to_clean->libs_tls_sects); @@ -896,25 +896,21 @@ parse_lib_dynamic_deps(Elf64_Shdr *dynamic_shdr, Elf64_Ehdr *lib_ehdr, } static void -find_comp_entry_points( - char **entry_points, size_t entry_point_count, struct Compartment *new_comp) +map_comp_entry_points(struct Compartment *new_comp) { - new_comp->entry_points - = malloc(entry_point_count * sizeof(struct CompEntryPoint)); - for (size_t i = 0; i < entry_point_count; ++i) + for (size_t i = 0; i < new_comp->cc->entry_point_count; ++i) { // TODO are entry points always in the main loaded library? // TODO is the main loaded library always the 0th indexed one? - struct LibSymSearchResult found_sym = find_lib_dep_sym_in_comp( - entry_points[i], new_comp, 0, STT_FUNC, true); + const char *ep_name = new_comp->cc->entry_points[i].name; + struct LibSymSearchResult found_sym + = find_lib_dep_sym_in_comp(ep_name, new_comp, 0, STT_FUNC, true); if (!found_sym.found) { - errx(1, "Did not find entry point %s!\n", entry_points[i]); + errx(1, "Did not find entry point %s!\n", ep_name); } - struct CompEntryPoint new_entry_point - = { entry_points[i], extract_sym_offset(new_comp, found_sym) }; - new_comp->entry_points[new_comp->entry_point_count] = new_entry_point; - new_comp->entry_point_count += 1; + new_comp->cc->entry_points[i].comp_addr + = extract_sym_offset(new_comp, found_sym); } } @@ -1161,8 +1157,8 @@ 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_heap_size = 0x800000UL; // TODO - new_comp->scratch_mem_stack_size = 0x80000UL; // TODO + 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( (char *) new_comp->scratch_mem_base + new_comp->scratch_mem_stack_size, 16); diff --git a/src/manager.c b/src/manager.c index e557b78..1f5f3dc 100644 --- a/src/manager.c +++ b/src/manager.c @@ -2,15 +2,18 @@ // TODO consider moving to a struct or some global thing static size_t comps_count = 0; -struct CompWithEntries **comps; +struct Compartment **comps; struct Compartment *loaded_comp = NULL; // Variables and functions related to laying compartments in memory // TODO make start address configurable -const uintptr_t comp_start_addr = 0x1000000UL; -const unsigned short comp_page_interval_count = 2; +static const uintptr_t comp_start_addr = 0x1000000UL; +static const unsigned short comp_page_interval_count = 2; void *min_next_comp_addr = NULL; +// Name of config file entry for compartment parameters +static const char *config_file_param_entry = "compconfig"; + void *__capability manager_ddc = 0; const char *comp_config_suffix = ".comp"; @@ -24,19 +27,25 @@ extern char **environ; // Functions +static struct CompConfig * +parse_compartment_config_file(char *, bool); +static void +parse_compartment_config_params(const toml_table_t *, struct CompConfig *); +static void +parse_compartment_config(struct CompConfig *); static struct CompEntryPointDef * -parse_compartment_config(char *, size_t *, bool); -static struct CompEntryPointDef * -make_default_entry_point(); +make_default_comp_entry_point(); +static struct CompConfig * +make_default_comp_config(); static struct CompEntryPointDef -get_entry_point(char *, struct CompEntryPointDef *, size_t); +get_entry_point(char *, const struct CompConfig *); static void prepare_compartment_environ(); static void * prepare_compartment_args(char **args, struct CompEntryPointDef); -static struct CompWithEntries * -get_comp_with_entries(struct Compartment *); +static struct Compartment * +get_comp(struct Compartment *); // Printing static void print_full_cap(uintcap_t); @@ -101,20 +110,13 @@ register_new_comp(char *filename, bool allow_default_entry) prepare_compartment_environ(); } - size_t new_comp_ep_count; - struct CompEntryPointDef *new_cep = parse_compartment_config( - filename, &new_comp_ep_count, allow_default_entry); + struct CompConfig *new_cc + = parse_compartment_config_file(filename, allow_default_entry); + new_cc->base_address = get_next_comp_addr(); - char **ep_names = calloc(new_comp_ep_count, sizeof(char *)); - for (size_t i = 0; i < new_comp_ep_count; ++i) - { - ep_names[i] = malloc(strlen(new_cep[i].name) + 1); - strcpy(ep_names[i], new_cep[i].name); - } - - struct Compartment *new_comp = comp_from_elf( - filename, ep_names, new_comp_ep_count, get_next_comp_addr()); + struct Compartment *new_comp = comp_from_elf(filename, new_cc); new_comp->id = comps_count; + new_comp->cc = new_cc; void *__capability new_comp_ddc = cheri_address_set(cheri_ddc_get(), (intptr_t) new_comp->base); new_comp_ddc = cheri_bounds_set( @@ -123,32 +125,22 @@ register_new_comp(char *filename, bool allow_default_entry) (char *) new_comp->scratch_mem_stack_top - (char *) new_comp->base); new_comp->ddc = new_comp_ddc; - struct CompWithEntries *new_cwe = malloc(sizeof(struct CompWithEntries)); - comps = realloc(comps, comps_count * sizeof(struct CompWithEntries *)); - comps[comps_count] = malloc(sizeof(struct CompWithEntries)); - comps[comps_count]->comp = new_comp; - comps[comps_count]->cep = new_cep; 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)); - for (size_t i = 0; i < new_comp_ep_count; ++i) - { - free(ep_names[i]); - } - free(ep_names); - return new_comp; } int64_t exec_comp(struct Compartment *to_exec, char *entry_fn, char **entry_fn_args) { - struct CompWithEntries *comp_to_run = get_comp_with_entries(to_exec); - struct CompEntryPointDef comp_entry = get_entry_point( - entry_fn, comp_to_run->cep, to_exec->entry_point_count); + struct CompEntryPointDef comp_entry + = get_entry_point(entry_fn, to_exec->cc); void *comp_args = prepare_compartment_args(entry_fn_args, comp_entry); struct Compartment *old_comp = loaded_comp; @@ -165,7 +157,7 @@ clean_all_comps() { for (size_t i = 0; i < comps_count; ++i) { - clean_comp(comps[i]->comp); + clean_comp(comps[i]); } free(comps); @@ -177,19 +169,15 @@ void clean_comp(struct Compartment *to_clean) { comp_clean(to_clean); - struct CompWithEntries *cwe = get_comp_with_entries(to_clean); - free(cwe->comp); - free(cwe->cep); - free(cwe); // TODO move around memory from `comps` } -static struct CompWithEntries * -get_comp_with_entries(struct Compartment *to_find) +static struct Compartment * +get_comp(struct Compartment *to_find) { for (size_t i = 0; i < comps_count; ++i) { - if (comps[i]->comp->id == to_find->id) + if (comps[i]->id == to_find->id) { return comps[i]; } @@ -203,15 +191,14 @@ manager_find_compartment_by_addr(void *addr) size_t i; for (i = 0; i < comps_count; ++i) { - if (comps[i]->comp->base <= addr - && (void *) ((char *) comps[i]->comp->base + comps[i]->comp->size) - > addr) + if (comps[i]->base <= addr + && (void *) ((char *) comps[i]->base + comps[i]->size) > addr) { break; } } assert(i != comps_count); - return comps[i]->comp; + return comps[i]; } struct Compartment * @@ -220,9 +207,9 @@ manager_find_compartment_by_ddc(void *__capability ddc) size_t i; for (i = 0; i < comps_count; ++i) { - if (comps[i]->comp->ddc == ddc) + if (comps[i]->ddc == ddc) { - return comps[i]->comp; + return comps[i]; } } // TODO improve error message with ddc @@ -233,7 +220,7 @@ struct Compartment * manager_get_compartment_by_id(size_t id) { assert(id < comps_count); - return comps[id]->comp; + return comps[id]; } void @@ -265,9 +252,23 @@ prep_config_filename(char *filename) return config_filename; } -static struct CompEntryPointDef * -parse_compartment_config( - char *comp_filename, size_t *entry_point_count, bool allow_default) +static void +parse_compartment_config_params( + const toml_table_t *params, struct CompConfig *cc) +{ + assert(params); + + toml_datum_t heap_sz_t = toml_int_in(params, "heap"); + assert(heap_sz_t.ok); + cc->heap_size = heap_sz_t.u.i; + + toml_datum_t stack_sz_t = toml_int_in(params, "stack"); + assert(stack_sz_t.ok); + cc->stack_size = stack_sz_t.u.i; +} + +static struct CompConfig * +parse_compartment_config_file(char *comp_filename, bool allow_default) { // Get config file name char *config_filename = prep_config_filename(comp_filename); @@ -277,10 +278,12 @@ parse_compartment_config( { assert(allow_default); errno = 0; - *entry_point_count = 1; - return make_default_entry_point(); + return make_default_comp_config(); } + struct CompConfig *new_cc = malloc(sizeof(struct CompConfig)); + bool explicit_comp_szs = false; + // Parse config file char toml_errbuf[200]; toml_table_t *tab @@ -289,63 +292,69 @@ parse_compartment_config( { toml_parse_error("TOML table parse error", toml_errbuf); } - *entry_point_count = toml_table_ntab(tab); - struct CompEntryPointDef *entry_points - = malloc(*entry_point_count * sizeof(struct CompEntryPointDef)); - for (size_t i = 0; i < *entry_point_count; ++i) + size_t entry_point_count = toml_table_ntab(tab); + new_cc->entry_point_count = entry_point_count; + toml_table_t *comp_params = toml_table_in(tab, config_file_param_entry); + if (comp_params) { - const char *fname = toml_key_in(tab, i); - assert(fname); - toml_table_t *curr_func = toml_table_in(tab, fname); - assert(curr_func); - toml_array_t *func_arg_types = toml_array_in(curr_func, "args_type"); - assert(func_arg_types); - size_t func_arg_count = toml_array_nelem(func_arg_types); - - entry_points[i].name = fname; - entry_points[i].arg_count = func_arg_count; - entry_points[i].args_type = malloc(func_arg_count * sizeof(char *)); - for (size_t j = 0; j < func_arg_count; ++j) - { - toml_datum_t func_arg_type = toml_string_at(func_arg_types, j); - entry_points[i].args_type[j] - = malloc(strlen(func_arg_type.u.s) + 1); - strcpy(entry_points[i].args_type[j], func_arg_type.u.s); - } + parse_compartment_config_params(comp_params, new_cc); + new_cc->entry_point_count -= 1; } - fclose(config_fd); - return entry_points; -} -void -clean_compartment_config( - struct CompEntryPointDef *cep, size_t entry_point_count) -{ - for (size_t i = 0; i < entry_point_count; ++i) + struct CompEntryPointDef *entry_points; + if (new_cc->entry_point_count == 0) + { + entry_points = make_default_comp_entry_point(); + new_cc->entry_point_count = 1; + } + else { - free((void *) cep[i].name); - for (size_t j = 0; j < cep[i].arg_count; ++j) + entry_points = calloc( + new_cc->entry_point_count, sizeof(struct CompEntryPointDef)); + for (size_t i = 0; i < entry_point_count; ++i) { - free(cep[i].args_type[j]); + const char *fname = toml_key_in(tab, i); + assert(fname); + if (!strcmp(fname, config_file_param_entry)) + { + break; + } + toml_table_t *curr_func = toml_table_in(tab, fname); + assert(curr_func); + toml_array_t *func_arg_types + = toml_array_in(curr_func, "args_type"); + assert(func_arg_types); + size_t func_arg_count = toml_array_nelem(func_arg_types); + + entry_points[i].name = malloc(strlen(fname) + 1); + strcpy(entry_points[i].name, fname); + entry_points[i].arg_count = func_arg_count; + entry_points[i].args_type = malloc(func_arg_count * sizeof(char *)); + entry_points[i].comp_addr = NULL; + for (size_t j = 0; j < func_arg_count; ++j) + { + toml_datum_t func_arg_type = toml_string_at(func_arg_types, j); + entry_points[i].args_type[j] + = malloc(strlen(func_arg_type.u.s) + 1); + strcpy(entry_points[i].args_type[j], func_arg_type.u.s); + } } - free(cep[i].args_type); } - free(cep); + new_cc->entry_points = entry_points; + fclose(config_fd); + return new_cc; } static struct CompEntryPointDef -get_entry_point( - char *entry_point_fn, struct CompEntryPointDef *ceps, size_t cep_count) +get_entry_point(char *entry_point_fn, const struct CompConfig *cc) { struct CompEntryPointDef curr_ep; - while (cep_count != 0) + for (size_t i = 0; i < cc->entry_point_count; ++i) { - curr_ep = ceps[cep_count - 1]; - if (!strcmp(curr_ep.name, entry_point_fn)) + if (!strcmp(cc->entry_points[i].name, entry_point_fn)) { - return curr_ep; + return cc->entry_points[i]; } - cep_count -= 1; } errx(1, "Did not find entry point for function %s!\n", entry_point_fn); } @@ -417,7 +426,7 @@ prepare_compartment_args(char **args, struct CompEntryPointDef cep) } static struct CompEntryPointDef * -make_default_entry_point() +make_default_comp_entry_point() { struct CompEntryPointDef *cep = malloc(sizeof(struct CompEntryPointDef)); cep->name = malloc(strlen("main") + 1); @@ -427,6 +436,18 @@ make_default_entry_point() return cep; } +static struct CompConfig * +make_default_comp_config() +{ + struct CompConfig *cc = malloc(sizeof(struct CompConfig)); + cc->heap_size = DEFAULT_COMP_HEAP_SZ; + 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; +} + static void print_comp(struct Compartment *to_print) { @@ -462,8 +483,6 @@ print_comp(struct Compartment *to_print) "- scratch_mem_stack_size : 0x%zx\n", to_print->scratch_mem_stack_size); printf("- libs_count : %lu\n", to_print->libs_count); - printf("- entry_point_count : %lu\n", to_print->entry_point_count); - // TODO entry_points printf("- tls_lookup_func : %p\n", to_print->tls_lookup_func); printf("- total_tls_size : %#zx\n", to_print->total_tls_size); printf("- libs_tls_sects :\n"); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index dcbfa47..9639328 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -185,7 +185,7 @@ set(tests "lua_simple" "lua_script" - #"lua_suite_some" + "lua_suite_some" "test_map" #"test_args_near_unmapped" diff --git a/tests/init_test.py b/tests/init_test.py index 866c870..a69de9c 100755 --- a/tests/init_test.py +++ b/tests/init_test.py @@ -26,12 +26,12 @@ LUA_TESTS_PATH = "./third-party/lua/testes" LUA_TESTS = [ - "calls.lua", - "goto.lua", "strings.lua", + "utf8.lua", + "goto.lua", "tpack.lua", "tracegc.lua", - "utf8.lua", + "calls.lua", ] ################################################################################ diff --git a/tests/lua_suite_some.c b/tests/lua_suite_some.c index 7d0d484..0ca95eb 100644 --- a/tests/lua_suite_some.c +++ b/tests/lua_suite_some.c @@ -10,7 +10,21 @@ int main() { const char *test_dir = "./lua"; - const char *test_names[] = { "strings.lua", "calls.lua", "utf8.lua" }; + const char *test_names[] = { "strings.lua", "utf8.lua", "goto.lua", + "tpack.lua", "tracegc.lua", "calls.lua" }; + // TODO disabled due to extremely long runtime; needs profiling + /*const char *test_names[] = { "gc.lua" };*/ + + /* `lua_dofile` not returning `LUA_OK`, even without compartmentalisation + * api.lua + * attrib.lua + * big.lua + * cstack.lua + */ + + /* Internally skipped tests (needs additional testing infrastructure support + * for `lua`) api.c + */ lua_State *L = luaL_newstate(); luaL_openlibs(L); diff --git a/tests/lua_suite_some.comp b/tests/lua_suite_some.comp new file mode 100644 index 0000000..03eeb43 --- /dev/null +++ b/tests/lua_suite_some.comp @@ -0,0 +1,3 @@ +[compconfig] +heap = 0x30000000 +stack = 0x800000