From 543cb940421ba12c9f1620f67ef898a05de8e9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Wed, 10 Sep 2025 22:18:43 +0200 Subject: [PATCH 01/19] wasmtime: extract running module into function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 146 +++++++++++++++++++++++--------- 1 file changed, 106 insertions(+), 40 deletions(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 7bcf052e41..fbc6f8e3f3 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef HAVE_DLOPEN # include @@ -44,16 +45,110 @@ #endif #if HAVE_DLOPEN && HAVE_WASMTIME +static void +libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t *wasm); + +static void +libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t *wasm); + static int libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, const char *pathname, char *const argv[]) { - size_t args_size = 0; - char *const *arg; wasm_byte_vec_t error_message; wasm_byte_vec_t wasm_bytes; wasm_engine_t *(*wasm_engine_new) (); wasmtime_error_t *(*wasmtime_wat2wasm) (const char *wat, size_t wat_len, wasm_byte_vec_t *out); + void (*wasm_byte_vec_new_uninitialized) (wasm_byte_vec_t *, size_t); + wasmtime_error_t *(*wasmtime_module_validate) (wasm_engine_t *engine, const uint8_t *wasm, size_t wasm_len); + void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message); + void (*wasmtime_error_delete) (wasmtime_error_t *error); + + wasmtime_wat2wasm = dlsym (cookie, "wasmtime_wat2wasm"); + wasm_engine_new = dlsym (cookie, "wasm_engine_new"); + wasm_byte_vec_new_uninitialized = dlsym (cookie, "wasm_byte_vec_new_uninitialized"); + wasmtime_module_validate = dlsym (cookie, "wasmtime_module_validate"); + wasmtime_error_delete = dlsym (cookie, "wasmtime_error_delete"); + wasmtime_error_message = dlsym (cookie, "wasmtime_error_message"); + + if (wasmtime_wat2wasm == NULL + || wasm_engine_new == NULL + || wasm_byte_vec_new_uninitialized == NULL + || wasmtime_module_validate == NULL + || wasmtime_error_delete == NULL + || wasmtime_error_message == NULL) + error (EXIT_FAILURE, 0, "could not find symbol in `libwasmtime.so`"); + + // Set up wasmtime context + wasm_engine_t *engine = wasm_engine_new (); + assert (engine != NULL); + + wasm_byte_vec_t wasm; + // Load and parse container entrypoint + FILE *file = fopen (pathname, "rbe"); + if (! file) + error (EXIT_FAILURE, 0, "error loading entrypoint"); + fseek (file, 0L, SEEK_END); + size_t file_size = ftell (file); + wasm_byte_vec_new_uninitialized (&wasm, file_size); + fseek (file, 0L, SEEK_SET); + if (fread (wasm.data, file_size, 1, file) != 1) + error (EXIT_FAILURE, 0, "error load"); + fclose (file); + + // If entrypoint contains a webassembly text format + // compile it on the fly and convert to equivalent + // binary format. + if (has_suffix (pathname, "wat") > 0) + { + wasmtime_error_t *err = wasmtime_wat2wasm ((char *) &wasm_bytes, file_size, &wasm); + if (err != NULL) + { + wasmtime_error_message (err, &error_message); + wasmtime_error_delete (err); + error (EXIT_FAILURE, 0, "failed while compiling wat to wasm binary : %.*s", (int) error_message.size, error_message.data); + } + wasm = wasm_bytes; + } + + // Check if it is a valid webassembly module or + // a component. + bool is_wasm_module = true; + wasmtime_error_t *err = wasmtime_module_validate (engine, (uint8_t *) wasm.data, wasm.size); + if (err != NULL) + { + wasmtime_error_message (err, &error_message); + wasmtime_error_delete (err); + + if (strcmp ((char *) error_message.data, "component passed to module validation") != 0) + { + error (EXIT_FAILURE, 0, "failed to validate module: %.*s", (int) error_message.size, error_message.data); + } + + err = NULL; + is_wasm_module = false; + } + + if (is_wasm_module) + { + libwasmtime_run_module (cookie, argv, engine, &wasm); + } + else + { + libwasmtime_run_component (cookie, argv, engine, &wasm); + } + + exit (EXIT_SUCCESS); +} + +static void +libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t *wasm) +{ + size_t args_size = 0; + char *const *arg; + wasm_byte_vec_t error_message; + + // Load needed functions void (*wasm_engine_delete) (wasm_engine_t *); void (*wasm_byte_vec_delete) (wasm_byte_vec_t *); void (*wasm_byte_vec_new_uninitialized) (wasm_byte_vec_t *, size_t); @@ -100,8 +195,6 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, void (*wasmtime_error_delete) (wasmtime_error_t *error); bool (*wasi_config_preopen_dir) (wasi_config_t *config, const char *path, const char *guest_path); - wasmtime_wat2wasm = dlsym (cookie, "wasmtime_wat2wasm"); - wasm_engine_new = dlsym (cookie, "wasm_engine_new"); wasm_engine_delete = dlsym (cookie, "wasm_engine_delete"); wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete"); wasm_byte_vec_new_uninitialized = dlsym (cookie, "wasm_byte_vec_new_uninitialized"); @@ -127,7 +220,7 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, wasmtime_error_message = dlsym (cookie, "wasmtime_error_message"); wasi_config_preopen_dir = dlsym (cookie, "wasi_config_preopen_dir"); - if (wasm_engine_new == NULL || wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL + if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL || wasm_byte_vec_new_uninitialized == NULL || wasi_config_new == NULL || wasmtime_store_new == NULL || wasmtime_store_context == NULL || wasmtime_linker_new == NULL || wasmtime_linker_define_wasi == NULL || wasmtime_module_new == NULL || wasi_config_inherit_argv == NULL || wasi_config_inherit_stdout == NULL @@ -135,13 +228,10 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, || wasi_config_inherit_env == NULL || wasmtime_context_set_wasi == NULL || wasmtime_linker_module == NULL || wasmtime_linker_get_default == NULL || wasmtime_func_call == NULL || wasmtime_module_delete == NULL || wasmtime_store_delete == NULL || wasi_config_set_argv == NULL - || wasmtime_error_delete == NULL || wasmtime_error_message == NULL || wasi_config_preopen_dir == NULL - || wasmtime_wat2wasm == NULL) + || wasmtime_error_delete == NULL || wasmtime_error_message == NULL || wasi_config_preopen_dir == NULL) error (EXIT_FAILURE, 0, "could not find symbol in `libwasmtime.so`"); // Set up wasmtime context - wasm_engine_t *engine = wasm_engine_new (); - assert (engine != NULL); wasmtime_store_t *store = wasmtime_store_new (engine, NULL, NULL); assert (store != NULL); wasmtime_context_t *context = wasmtime_store_context (store); @@ -156,44 +246,16 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, error (EXIT_FAILURE, 0, "failed to link wasi: %.*s", (int) error_message.size, error_message.data); } - wasm_byte_vec_t wasm; - // Load and parse container entrypoint - FILE *file = fopen (pathname, "rbe"); - if (! file) - error (EXIT_FAILURE, 0, "error loading entrypoint"); - fseek (file, 0L, SEEK_END); - size_t file_size = ftell (file); - wasm_byte_vec_new_uninitialized (&wasm, file_size); - fseek (file, 0L, SEEK_SET); - if (fread (wasm.data, file_size, 1, file) != 1) - error (EXIT_FAILURE, 0, "error load"); - fclose (file); - - // If entrypoint contains a webassembly text format - // compile it on the fly and convert to equivalent - // binary format. - if (has_suffix (pathname, "wat") > 0) - { - wasmtime_error_t *err = wasmtime_wat2wasm ((char *) &wasm_bytes, file_size, &wasm); - if (err != NULL) - { - wasmtime_error_message (err, &error_message); - wasmtime_error_delete (err); - error (EXIT_FAILURE, 0, "failed while compiling wat to wasm binary : %.*s", (int) error_message.size, error_message.data); - } - wasm = wasm_bytes; - } - // Compile wasm modules wasmtime_module_t *module = NULL; - err = wasmtime_module_new (engine, (uint8_t *) wasm.data, wasm.size, &module); + err = wasmtime_module_new (engine, (uint8_t *) wasm->data, wasm->size, &module); if (! module) { wasmtime_error_message (err, &error_message); wasmtime_error_delete (err); error (EXIT_FAILURE, 0, "failed to compile module: %.*s", (int) error_message.size, error_message.data); } - wasm_byte_vec_delete (&wasm); + wasm_byte_vec_delete (wasm); // Init WASI program wasi_config_t *wasi_config = wasi_config_new ("crun_wasi_program"); @@ -249,8 +311,12 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, wasmtime_module_delete (module); wasmtime_store_delete (store); wasm_engine_delete (engine); +} - exit (EXIT_SUCCESS); +static void +libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t *wasm) +{ + error (EXIT_FAILURE, 0, "running components is not yet implemented!"); } static int From d878baf71e8b028fb5079501c6897dc66ffe9780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Wed, 10 Sep 2025 22:57:18 +0200 Subject: [PATCH 02/19] wasmtime: Implement basic WASIp2 components support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 173 +++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 4 deletions(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index fbc6f8e3f3..0c180517df 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -15,6 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with crun. If not, see . */ +#include #define _GNU_SOURCE #include @@ -151,7 +152,6 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, // Load needed functions void (*wasm_engine_delete) (wasm_engine_t *); void (*wasm_byte_vec_delete) (wasm_byte_vec_t *); - void (*wasm_byte_vec_new_uninitialized) (wasm_byte_vec_t *, size_t); wasi_config_t *(*wasi_config_new) (const char *); wasmtime_store_t *(*wasmtime_store_new) (wasm_engine_t *engine, void *data, void (*finalizer) (void *)); wasmtime_context_t *(*wasmtime_store_context) (wasmtime_store_t *store); @@ -197,7 +197,6 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_engine_delete = dlsym (cookie, "wasm_engine_delete"); wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete"); - wasm_byte_vec_new_uninitialized = dlsym (cookie, "wasm_byte_vec_new_uninitialized"); wasi_config_new = dlsym (cookie, "wasi_config_new"); wasi_config_set_argv = dlsym (cookie, "wasi_config_set_argv"); wasmtime_store_new = dlsym (cookie, "wasmtime_store_new"); @@ -221,7 +220,7 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, wasi_config_preopen_dir = dlsym (cookie, "wasi_config_preopen_dir"); if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL - || wasm_byte_vec_new_uninitialized == NULL || wasi_config_new == NULL || wasmtime_store_new == NULL + || wasi_config_new == NULL || wasmtime_store_new == NULL || wasmtime_store_context == NULL || wasmtime_linker_new == NULL || wasmtime_linker_define_wasi == NULL || wasmtime_module_new == NULL || wasi_config_inherit_argv == NULL || wasi_config_inherit_stdout == NULL || wasi_config_inherit_stdin == NULL || wasi_config_inherit_stderr == NULL @@ -316,7 +315,173 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, static void libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t *wasm) { - error (EXIT_FAILURE, 0, "running components is not yet implemented!"); + const char *wasi_cli_run_interface = "wasi:cli/run@0.2.0"; + const char *wasi_cli_run_interface_run = "run"; + wasm_byte_vec_t error_message; + + // Load needed functions + void (*wasm_engine_delete) (wasm_engine_t *); + void (*wasm_byte_vec_delete) (wasm_byte_vec_t *); + wasmtime_store_t *(*wasmtime_store_new) (wasm_engine_t *engine, void *data, void (*finalizer) (void *)); + void (*wasmtime_store_delete) (wasmtime_store_t *store); + wasmtime_context_t *(*wasmtime_store_context) (wasmtime_store_t *store); + wasmtime_error_t *(*wasmtime_component_new) ( + const wasm_engine_t *engine, + const uint8_t *buf, + size_t len, + wasmtime_component_t **component_out); + wasmtime_wasip2_config_t *(*wasmtime_wasip2_config_new) (void); + void (*wasmtime_wasip2_config_inherit_stdin) (wasmtime_wasip2_config_t *config); + void (*wasmtime_wasip2_config_inherit_stdout) (wasmtime_wasip2_config_t *config); + void (*wasmtime_wasip2_config_inherit_stderr) (wasmtime_wasip2_config_t *config); + void (*wasmtime_context_set_wasip2) (wasmtime_context_t *context, wasmtime_wasip2_config_t *config); + wasmtime_component_linker_t *(*wasmtime_component_linker_new) (wasm_engine_t *engine); + wasmtime_error_t *(*wasmtime_component_linker_add_wasip2) (wasmtime_component_linker_t *linker); + wasmtime_error_t *(*wasmtime_component_linker_instantiate) ( + const wasmtime_component_linker_t *linker, + wasmtime_context_t *context, + const wasmtime_component_t *component, + wasmtime_component_instance_t *instance_out); + wasmtime_component_export_index_t *(*wasmtime_component_get_export_index) ( + wasmtime_component_t *component, + wasmtime_component_export_index_t *index, + const char *name, + size_t name_len); + wasmtime_component_export_index_t *(*wasmtime_component_instance_get_export_index) ( + const wasmtime_component_instance_t *instance, + wasmtime_context_t *context, + const wasmtime_component_export_index_t *instance_export_index, + const char *name, + size_t name_len); + bool (*wasmtime_component_instance_get_func) ( + const wasmtime_component_instance_t *instance, + wasmtime_context_t *context, + const wasmtime_component_export_index_t *export_index, + wasmtime_component_func_t *func_out); + wasmtime_error_t *(*wasmtime_component_func_call) ( + const wasmtime_component_func_t *func, + wasmtime_context_t *context, + const wasmtime_component_val_t *args, + size_t args_size, + wasmtime_component_val_t *results, + size_t results_size); + void (*wasmtime_component_export_index_delete) (wasmtime_component_export_index_t *export_index); + void (*wasmtime_component_delete) (wasmtime_component_t *c); + void (*wasmtime_component_linker_delete) (wasmtime_component_linker_t *linker); + void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message); + void (*wasmtime_error_delete) (wasmtime_error_t *error); + + wasm_engine_delete = dlsym (cookie, "wasm_engine_delete"); + wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete"); + wasmtime_store_new = dlsym (cookie, "wasmtime_store_new"); + wasmtime_store_delete = dlsym (cookie, "wasmtime_store_delete"); + wasmtime_store_context = dlsym (cookie, "wasmtime_store_context"); + wasmtime_component_new = dlsym (cookie, "wasmtime_component_new"); + wasmtime_wasip2_config_new = dlsym (cookie, "wasmtime_wasip2_config_new"); + wasmtime_wasip2_config_inherit_stdin = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdin"); + wasmtime_wasip2_config_inherit_stdout = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdout"); + wasmtime_wasip2_config_inherit_stderr = dlsym (cookie, "wasmtime_wasip2_config_inherit_stderr"); + wasmtime_context_set_wasip2 = dlsym (cookie, "wasmtime_context_set_wasip2"); + wasmtime_component_linker_new = dlsym (cookie, "wasmtime_component_linker_new"); + wasmtime_component_linker_add_wasip2 = dlsym (cookie, "wasmtime_component_linker_add_wasip2"); + wasmtime_component_linker_instantiate = dlsym (cookie, "wasmtime_component_linker_instantiate"); + wasmtime_component_get_export_index = dlsym (cookie, "wasmtime_component_get_export_index"); + wasmtime_component_instance_get_export_index = dlsym (cookie, "wasmtime_component_instance_get_export_index"); + wasmtime_component_instance_get_func = dlsym (cookie, "wasmtime_component_instance_get_func"); + wasmtime_component_func_call = dlsym (cookie, "wasmtime_component_func_call"); + wasmtime_component_export_index_delete = dlsym (cookie, "wasmtime_component_export_index_delete"); + wasmtime_component_delete = dlsym (cookie, "wasmtime_component_delete"); + wasmtime_component_linker_delete = dlsym (cookie, "wasmtime_component_linker_delete"); + wasmtime_error_message = dlsym (cookie, "wasmtime_error_message"); + wasmtime_error_delete = dlsym (cookie, "wasmtime_error_delete"); + + // Set up wasmtime context + wasmtime_store_t *store = wasmtime_store_new (engine, NULL, NULL); + assert (store != NULL); + wasmtime_context_t *context = wasmtime_store_context (store); + + // Compile wasm component + wasmtime_component_t *component = NULL; + wasmtime_error_t *err = wasmtime_component_new (engine, (uint8_t *) wasm->data, wasm->size, &component); + if (! component || err != NULL) + { + wasmtime_error_message (err, &error_message); + wasmtime_error_delete (err); + error (EXIT_FAILURE, 0, "failed to compile component: %.*s", (int) error_message.size, error_message.data); + } + wasm_byte_vec_delete (wasm); + + // Set up WASIp2 config + wasmtime_wasip2_config_t *wasi_config = wasmtime_wasip2_config_new (); + assert (wasi_config != NULL); + + wasmtime_wasip2_config_inherit_stdin (wasi_config); + wasmtime_wasip2_config_inherit_stdout (wasi_config); + wasmtime_wasip2_config_inherit_stderr (wasi_config); + // TODO: argv + wasmtime_context_set_wasip2 (context, wasi_config); + + // Get wasi exposing linker + wasmtime_component_linker_t *linker = wasmtime_component_linker_new (engine); + err = wasmtime_component_linker_add_wasip2 (linker); + if (err != NULL) + { + wasmtime_error_message (err, &error_message); + wasmtime_error_delete (err); + error (EXIT_FAILURE, 0, "failed to add WASIp2 to linker: %.*s", (int) error_message.size, error_message.data); + } + + // Instantiate the component + wasmtime_component_instance_t component_inst = {}; + err = wasmtime_component_linker_instantiate (linker, context, component, &component_inst); + if (err != NULL) + { + wasmtime_error_message (err, &error_message); + wasmtime_error_delete (err); + error (EXIT_FAILURE, 0, "failed to instantiate component: %.*s", (int) error_message.size, error_message.data); + } + + // Get index of the run interface in wasi/cli world + wasmtime_component_export_index_t *run_interface_idx = wasmtime_component_instance_get_export_index ( + &component_inst, + context, + NULL, + wasi_cli_run_interface, + strlen (wasi_cli_run_interface)); + assert (run_interface_idx != NULL); + // Get index of the run function + wasmtime_component_export_index_t *run_func_idx = wasmtime_component_instance_get_export_index ( + &component_inst, + context, + run_interface_idx, + wasi_cli_run_interface_run, + strlen (wasi_cli_run_interface_run)); + assert (run_func_idx != NULL); + + // Actually retrieve the func + wasmtime_component_func_t run_func = {}; + if (! wasmtime_component_instance_get_func (&component_inst, context, run_func_idx, &run_func)) + { + error (EXIT_FAILURE, 0, "failed to retrieve run function"); + } + + // Call the func + wasmtime_component_val_t result = {}; + err = wasmtime_component_func_call (&run_func, context, NULL, 0, &result, 1); + if (err != NULL) + { + wasmtime_error_message (err, &error_message); + wasmtime_error_delete (err); + error (EXIT_FAILURE, 0, "error calling run function: %.*s", (int) error_message.size, error_message.data); + } + + // Clean everything + wasmtime_component_export_index_delete (run_func_idx); + wasmtime_component_export_index_delete (run_interface_idx); + wasmtime_component_linker_delete (linker); + wasmtime_component_delete (component); + wasmtime_store_delete (store); + wasm_engine_delete (engine); } static int From c05cf2e498ead94e6e2739de69325f25504877bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Wed, 10 Sep 2025 23:08:21 +0200 Subject: [PATCH 03/19] wasmtime: Check functions after manual loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 0c180517df..8ab043742d 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -15,7 +15,6 @@ * You should have received a copy of the GNU Lesser General Public License * along with crun. If not, see . */ -#include #define _GNU_SOURCE #include @@ -342,11 +341,6 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_context_t *context, const wasmtime_component_t *component, wasmtime_component_instance_t *instance_out); - wasmtime_component_export_index_t *(*wasmtime_component_get_export_index) ( - wasmtime_component_t *component, - wasmtime_component_export_index_t *index, - const char *name, - size_t name_len); wasmtime_component_export_index_t *(*wasmtime_component_instance_get_export_index) ( const wasmtime_component_instance_t *instance, wasmtime_context_t *context, @@ -385,7 +379,6 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_component_linker_new = dlsym (cookie, "wasmtime_component_linker_new"); wasmtime_component_linker_add_wasip2 = dlsym (cookie, "wasmtime_component_linker_add_wasip2"); wasmtime_component_linker_instantiate = dlsym (cookie, "wasmtime_component_linker_instantiate"); - wasmtime_component_get_export_index = dlsym (cookie, "wasmtime_component_get_export_index"); wasmtime_component_instance_get_export_index = dlsym (cookie, "wasmtime_component_instance_get_export_index"); wasmtime_component_instance_get_func = dlsym (cookie, "wasmtime_component_instance_get_func"); wasmtime_component_func_call = dlsym (cookie, "wasmtime_component_func_call"); @@ -395,6 +388,17 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_error_message = dlsym (cookie, "wasmtime_error_message"); wasmtime_error_delete = dlsym (cookie, "wasmtime_error_delete"); + if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL || wasmtime_store_new == NULL + || wasmtime_store_delete == NULL || wasmtime_store_context == NULL || wasmtime_component_new == NULL + || wasmtime_wasip2_config_new == NULL || wasmtime_wasip2_config_inherit_stdin == NULL + || wasmtime_wasip2_config_inherit_stdout == NULL || wasmtime_wasip2_config_inherit_stderr == NULL + || wasmtime_context_set_wasip2 == NULL || wasmtime_component_linker_new == NULL || wasmtime_component_linker_add_wasip2 == NULL + || wasmtime_component_linker_instantiate == NULL || wasmtime_component_instance_get_export_index == NULL + || wasmtime_component_instance_get_func == NULL || wasmtime_component_func_call == NULL || wasmtime_component_export_index_delete == NULL + || wasmtime_component_delete == NULL || wasmtime_component_linker_delete == NULL || wasmtime_error_message == NULL + || wasmtime_error_delete == NULL) + error (EXIT_FAILURE, 0, "could not find symbol in `libwasmtime.so`"); + // Set up wasmtime context wasmtime_store_t *store = wasmtime_store_new (engine, NULL, NULL); assert (store != NULL); From ce7d6562308bb821e7ddc787980ba08dceead8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Wed, 10 Sep 2025 23:33:25 +0200 Subject: [PATCH 04/19] wasmtime: Add argv to wasm components; Change CMD to ENTRYPOINT in wasm-wasi-example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In docs/wasm-wasi-example.md the Containerfile had the WebAssembly binary in the `CMD` instruction. But running the container via podman like so `podman run mywasm-image:latest arg1 arg2` does not work as podman instructs crun to run `arg1 arg2` instead of `hello.wasm arg1 arg2` resulting in the error `arg1: command not found`. Using `ENTRYPOINT` in the Containerfile makes the previously mentioned podman command work. Signed-off-by: Maximilian Hüter --- docs/wasm-wasi-example.md | 2 +- src/libcrun/handlers/wasmtime.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/wasm-wasi-example.md b/docs/wasm-wasi-example.md index eae26de9d2..1dea658519 100644 --- a/docs/wasm-wasi-example.md +++ b/docs/wasm-wasi-example.md @@ -40,7 +40,7 @@ This is from a main function from a wasm module ```Containerfile FROM scratch COPY hello.wasm / -CMD ["/hello.wasm"] +ENTRYPOINT ["/hello.wasm"] ``` * Build wasm image using buildah ```console diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 8ab043742d..1c092496e3 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -314,8 +314,9 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, static void libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t *wasm) { - const char *wasi_cli_run_interface = "wasi:cli/run@0.2.0"; - const char *wasi_cli_run_interface_run = "run"; + const char *const wasi_cli_run_interface = "wasi:cli/run@0.2.0"; + const char *const wasi_cli_run_interface_run = "run"; + char *const *arg; wasm_byte_vec_t error_message; // Load needed functions @@ -333,6 +334,7 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi void (*wasmtime_wasip2_config_inherit_stdin) (wasmtime_wasip2_config_t *config); void (*wasmtime_wasip2_config_inherit_stdout) (wasmtime_wasip2_config_t *config); void (*wasmtime_wasip2_config_inherit_stderr) (wasmtime_wasip2_config_t *config); + void (*wasmtime_wasip2_config_arg) (wasmtime_wasip2_config_t *config, const char *arg, size_t arg_len); void (*wasmtime_context_set_wasip2) (wasmtime_context_t *context, wasmtime_wasip2_config_t *config); wasmtime_component_linker_t *(*wasmtime_component_linker_new) (wasm_engine_t *engine); wasmtime_error_t *(*wasmtime_component_linker_add_wasip2) (wasmtime_component_linker_t *linker); @@ -375,6 +377,7 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_wasip2_config_inherit_stdin = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdin"); wasmtime_wasip2_config_inherit_stdout = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdout"); wasmtime_wasip2_config_inherit_stderr = dlsym (cookie, "wasmtime_wasip2_config_inherit_stderr"); + wasmtime_wasip2_config_arg = dlsym (cookie, "wasmtime_wasip2_config_arg"); wasmtime_context_set_wasip2 = dlsym (cookie, "wasmtime_context_set_wasip2"); wasmtime_component_linker_new = dlsym (cookie, "wasmtime_component_linker_new"); wasmtime_component_linker_add_wasip2 = dlsym (cookie, "wasmtime_component_linker_add_wasip2"); @@ -391,7 +394,7 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL || wasmtime_store_new == NULL || wasmtime_store_delete == NULL || wasmtime_store_context == NULL || wasmtime_component_new == NULL || wasmtime_wasip2_config_new == NULL || wasmtime_wasip2_config_inherit_stdin == NULL - || wasmtime_wasip2_config_inherit_stdout == NULL || wasmtime_wasip2_config_inherit_stderr == NULL + || wasmtime_wasip2_config_inherit_stdout == NULL || wasmtime_wasip2_config_inherit_stderr == NULL || wasmtime_wasip2_config_arg == NULL || wasmtime_context_set_wasip2 == NULL || wasmtime_component_linker_new == NULL || wasmtime_component_linker_add_wasip2 == NULL || wasmtime_component_linker_instantiate == NULL || wasmtime_component_instance_get_export_index == NULL || wasmtime_component_instance_get_func == NULL || wasmtime_component_func_call == NULL || wasmtime_component_export_index_delete == NULL @@ -422,7 +425,10 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_wasip2_config_inherit_stdin (wasi_config); wasmtime_wasip2_config_inherit_stdout (wasi_config); wasmtime_wasip2_config_inherit_stderr (wasi_config); - // TODO: argv + + for (arg = argv; *arg != NULL; ++arg) + wasmtime_wasip2_config_arg (wasi_config, *arg, strlen (*arg)); + wasmtime_context_set_wasip2 (context, wasi_config); // Get wasi exposing linker From dc2e2e1645f01f67a35896548fa46f19654fa6b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Thu, 11 Sep 2025 13:03:07 +0200 Subject: [PATCH 05/19] wasmtime: have wasip2 inherit env MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 1c092496e3..2c77d777a9 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -331,6 +331,7 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi size_t len, wasmtime_component_t **component_out); wasmtime_wasip2_config_t *(*wasmtime_wasip2_config_new) (void); + void (*wasi_config_inherit_env) (wasi_config_t *config); void (*wasmtime_wasip2_config_inherit_stdin) (wasmtime_wasip2_config_t *config); void (*wasmtime_wasip2_config_inherit_stdout) (wasmtime_wasip2_config_t *config); void (*wasmtime_wasip2_config_inherit_stderr) (wasmtime_wasip2_config_t *config); @@ -374,6 +375,7 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_store_context = dlsym (cookie, "wasmtime_store_context"); wasmtime_component_new = dlsym (cookie, "wasmtime_component_new"); wasmtime_wasip2_config_new = dlsym (cookie, "wasmtime_wasip2_config_new"); + wasi_config_inherit_env = dlsym (cookie, "wasi_config_inherit_env"); wasmtime_wasip2_config_inherit_stdin = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdin"); wasmtime_wasip2_config_inherit_stdout = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdout"); wasmtime_wasip2_config_inherit_stderr = dlsym (cookie, "wasmtime_wasip2_config_inherit_stderr"); @@ -393,7 +395,7 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL || wasmtime_store_new == NULL || wasmtime_store_delete == NULL || wasmtime_store_context == NULL || wasmtime_component_new == NULL - || wasmtime_wasip2_config_new == NULL || wasmtime_wasip2_config_inherit_stdin == NULL + || wasmtime_wasip2_config_new == NULL || wasi_config_inherit_env == NULL || wasmtime_wasip2_config_inherit_stdin == NULL || wasmtime_wasip2_config_inherit_stdout == NULL || wasmtime_wasip2_config_inherit_stderr == NULL || wasmtime_wasip2_config_arg == NULL || wasmtime_context_set_wasip2 == NULL || wasmtime_component_linker_new == NULL || wasmtime_component_linker_add_wasip2 == NULL || wasmtime_component_linker_instantiate == NULL || wasmtime_component_instance_get_export_index == NULL @@ -422,6 +424,7 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_wasip2_config_t *wasi_config = wasmtime_wasip2_config_new (); assert (wasi_config != NULL); + wasi_config_inherit_env ((wasi_config_t *) wasi_config); wasmtime_wasip2_config_inherit_stdin (wasi_config); wasmtime_wasip2_config_inherit_stdout (wasi_config); wasmtime_wasip2_config_inherit_stderr (wasi_config); From b1c4da5a8ff6be303059d7dd31574027c2ab97bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Thu, 11 Sep 2025 13:28:14 +0200 Subject: [PATCH 06/19] wasmtime: Fix wat to wasm compiling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 2c77d777a9..850248933c 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -60,6 +60,7 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, wasm_engine_t *(*wasm_engine_new) (); wasmtime_error_t *(*wasmtime_wat2wasm) (const char *wat, size_t wat_len, wasm_byte_vec_t *out); void (*wasm_byte_vec_new_uninitialized) (wasm_byte_vec_t *, size_t); + void (*wasm_byte_vec_delete) (wasm_byte_vec_t *); wasmtime_error_t *(*wasmtime_module_validate) (wasm_engine_t *engine, const uint8_t *wasm, size_t wasm_len); void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message); void (*wasmtime_error_delete) (wasmtime_error_t *error); @@ -67,6 +68,7 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, wasmtime_wat2wasm = dlsym (cookie, "wasmtime_wat2wasm"); wasm_engine_new = dlsym (cookie, "wasm_engine_new"); wasm_byte_vec_new_uninitialized = dlsym (cookie, "wasm_byte_vec_new_uninitialized"); + wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete"); wasmtime_module_validate = dlsym (cookie, "wasmtime_module_validate"); wasmtime_error_delete = dlsym (cookie, "wasmtime_error_delete"); wasmtime_error_message = dlsym (cookie, "wasmtime_error_message"); @@ -74,6 +76,7 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, if (wasmtime_wat2wasm == NULL || wasm_engine_new == NULL || wasm_byte_vec_new_uninitialized == NULL + || wasm_byte_vec_delete == NULL || wasmtime_module_validate == NULL || wasmtime_error_delete == NULL || wasmtime_error_message == NULL) @@ -101,13 +104,14 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, // binary format. if (has_suffix (pathname, "wat") > 0) { - wasmtime_error_t *err = wasmtime_wat2wasm ((char *) &wasm_bytes, file_size, &wasm); + wasmtime_error_t *err = wasmtime_wat2wasm ((char *) wasm.data, file_size, &wasm_bytes); if (err != NULL) { wasmtime_error_message (err, &error_message); wasmtime_error_delete (err); error (EXIT_FAILURE, 0, "failed while compiling wat to wasm binary : %.*s", (int) error_message.size, error_message.data); } + wasm_byte_vec_delete (&wasm); wasm = wasm_bytes; } From 9a073f6caa554c2dd2b2d89d0b4463c863005e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Fri, 12 Sep 2025 13:50:49 +0200 Subject: [PATCH 07/19] wasmtime: misc code cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 44 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 850248933c..ce6e2bb775 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -84,17 +83,20 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, // Set up wasmtime context wasm_engine_t *engine = wasm_engine_new (); - assert (engine != NULL); + if (engine == NULL) + error (EXIT_FAILURE, 0, "could not create WebAssembly engine"); wasm_byte_vec_t wasm; // Load and parse container entrypoint FILE *file = fopen (pathname, "rbe"); if (! file) error (EXIT_FAILURE, 0, "error loading entrypoint"); - fseek (file, 0L, SEEK_END); + if (fseek (file, 0L, SEEK_END)) + error (EXIT_FAILURE, 0, "error fully loading entrypoint"); size_t file_size = ftell (file); wasm_byte_vec_new_uninitialized (&wasm, file_size); - fseek (file, 0L, SEEK_SET); + if (fseek (file, 0L, SEEK_SET)) + error (EXIT_FAILURE, 0, "error resetting entrypoint"); if (fread (wasm.data, file_size, 1, file) != 1) error (EXIT_FAILURE, 0, "error load"); fclose (file); @@ -125,22 +127,16 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, wasmtime_error_delete (err); if (strcmp ((char *) error_message.data, "component passed to module validation") != 0) - { - error (EXIT_FAILURE, 0, "failed to validate module: %.*s", (int) error_message.size, error_message.data); - } + error (EXIT_FAILURE, 0, "failed to validate module: %.*s", (int) error_message.size, error_message.data); err = NULL; is_wasm_module = false; } if (is_wasm_module) - { - libwasmtime_run_module (cookie, argv, engine, &wasm); - } + libwasmtime_run_module (cookie, argv, engine, &wasm); else - { - libwasmtime_run_component (cookie, argv, engine, &wasm); - } + libwasmtime_run_component (cookie, argv, engine, &wasm); exit (EXIT_SUCCESS); } @@ -235,7 +231,8 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, // Set up wasmtime context wasmtime_store_t *store = wasmtime_store_new (engine, NULL, NULL); - assert (store != NULL); + if (store == NULL) + error (EXIT_FAILURE, 0, "could not create WebAssembly store"); wasmtime_context_t *context = wasmtime_store_context (store); // Link with wasi functions defined @@ -261,7 +258,8 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, // Init WASI program wasi_config_t *wasi_config = wasi_config_new ("crun_wasi_program"); - assert (wasi_config); + if (wasi_config == NULL) + error (EXIT_FAILURE, 0, "could not create WASI configuration"); // Calculate argc for `wasi_config_set_argv` for (arg = argv; *arg != NULL; ++arg) @@ -410,7 +408,8 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi // Set up wasmtime context wasmtime_store_t *store = wasmtime_store_new (engine, NULL, NULL); - assert (store != NULL); + if (store == NULL) + error (EXIT_FAILURE, 0, "could not create WebAssembly store"); wasmtime_context_t *context = wasmtime_store_context (store); // Compile wasm component @@ -426,7 +425,8 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi // Set up WASIp2 config wasmtime_wasip2_config_t *wasi_config = wasmtime_wasip2_config_new (); - assert (wasi_config != NULL); + if (wasi_config == NULL) + error (EXIT_FAILURE, 0, "could not create WASIp2 configuration"); wasi_config_inherit_env ((wasi_config_t *) wasi_config); wasmtime_wasip2_config_inherit_stdin (wasi_config); @@ -465,7 +465,8 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi NULL, wasi_cli_run_interface, strlen (wasi_cli_run_interface)); - assert (run_interface_idx != NULL); + if (run_interface_idx == NULL) + error (EXIT_FAILURE, 0, "failed to fetch export index of %.*s", (int) strlen (wasi_cli_run_interface), wasi_cli_run_interface); // Get index of the run function wasmtime_component_export_index_t *run_func_idx = wasmtime_component_instance_get_export_index ( &component_inst, @@ -473,14 +474,13 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi run_interface_idx, wasi_cli_run_interface_run, strlen (wasi_cli_run_interface_run)); - assert (run_func_idx != NULL); + if (run_func_idx == NULL) + error (EXIT_FAILURE, 0, "failed to fetch export index of %.*s", (int) strlen (wasi_cli_run_interface_run), wasi_cli_run_interface_run); // Actually retrieve the func wasmtime_component_func_t run_func = {}; if (! wasmtime_component_instance_get_func (&component_inst, context, run_func_idx, &run_func)) - { - error (EXIT_FAILURE, 0, "failed to retrieve run function"); - } + error (EXIT_FAILURE, 0, "failed to retrieve run function"); // Call the func wasmtime_component_val_t result = {}; From e8cbc72374104b3b254e1a335134df7edfc8444c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Fri, 19 Sep 2025 11:46:53 +0200 Subject: [PATCH 08/19] wasmtime: expand reading entrypoint error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index ce6e2bb775..cb9cd09442 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -98,7 +98,7 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, if (fseek (file, 0L, SEEK_SET)) error (EXIT_FAILURE, 0, "error resetting entrypoint"); if (fread (wasm.data, file_size, 1, file) != 1) - error (EXIT_FAILURE, 0, "error load"); + error (EXIT_FAILURE, 0, "error reading entrypoint"); fclose (file); // If entrypoint contains a webassembly text format From 741045ab6fa0fe05756d26711ff2297cd2a00a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Thu, 11 Sep 2025 12:58:41 +0200 Subject: [PATCH 09/19] wasmtime: Fix and Add preopen_dir for modules & components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index cb9cd09442..49f315f308 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -192,7 +192,12 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, void (*wasmtime_store_delete) (wasmtime_store_t *store); void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message); void (*wasmtime_error_delete) (wasmtime_error_t *error); - bool (*wasi_config_preopen_dir) (wasi_config_t *config, const char *path, const char *guest_path); + bool (*wasi_config_preopen_dir) ( + wasi_config_t *config, + const char *path, + const char *guest_path, + wasi_dir_perms dir_perms, + wasi_file_perms file_perms); wasm_engine_delete = dlsym (cookie, "wasm_engine_delete"); wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete"); @@ -270,7 +275,12 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, wasi_config_inherit_stdin (wasi_config); wasi_config_inherit_stdout (wasi_config); wasi_config_inherit_stderr (wasi_config); - wasi_config_preopen_dir (wasi_config, ".", "."); + wasi_config_preopen_dir ( + wasi_config, + ".", + ".", + WASMTIME_WASI_DIR_PERMS_READ | WASMTIME_WASI_DIR_PERMS_WRITE, + WASMTIME_WASI_FILE_PERMS_READ | WASMTIME_WASI_FILE_PERMS_WRITE); wasm_trap_t *trap = NULL; err = wasmtime_context_set_wasi (context, wasi_config); if (err != NULL) @@ -369,6 +379,12 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi void (*wasmtime_component_linker_delete) (wasmtime_component_linker_t *linker); void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message); void (*wasmtime_error_delete) (wasmtime_error_t *error); + bool (*wasi_config_preopen_dir) ( + wasi_config_t *config, + const char *path, + const char *guest_path, + wasi_dir_perms dir_perms, + wasi_file_perms file_perms); wasm_engine_delete = dlsym (cookie, "wasm_engine_delete"); wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete"); @@ -394,6 +410,7 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_component_linker_delete = dlsym (cookie, "wasmtime_component_linker_delete"); wasmtime_error_message = dlsym (cookie, "wasmtime_error_message"); wasmtime_error_delete = dlsym (cookie, "wasmtime_error_delete"); + wasi_config_preopen_dir = dlsym (cookie, "wasi_config_preopen_dir"); if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL || wasmtime_store_new == NULL || wasmtime_store_delete == NULL || wasmtime_store_context == NULL || wasmtime_component_new == NULL @@ -403,7 +420,7 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi || wasmtime_component_linker_instantiate == NULL || wasmtime_component_instance_get_export_index == NULL || wasmtime_component_instance_get_func == NULL || wasmtime_component_func_call == NULL || wasmtime_component_export_index_delete == NULL || wasmtime_component_delete == NULL || wasmtime_component_linker_delete == NULL || wasmtime_error_message == NULL - || wasmtime_error_delete == NULL) + || wasmtime_error_delete == NULL || wasi_config_preopen_dir == NULL) error (EXIT_FAILURE, 0, "could not find symbol in `libwasmtime.so`"); // Set up wasmtime context @@ -432,6 +449,12 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_wasip2_config_inherit_stdin (wasi_config); wasmtime_wasip2_config_inherit_stdout (wasi_config); wasmtime_wasip2_config_inherit_stderr (wasi_config); + wasi_config_preopen_dir ( + (wasi_config_t *) wasi_config, + ".", + ".", + WASMTIME_WASI_DIR_PERMS_READ | WASMTIME_WASI_DIR_PERMS_WRITE, + WASMTIME_WASI_FILE_PERMS_READ | WASMTIME_WASI_FILE_PERMS_WRITE); for (arg = argv; *arg != NULL; ++arg) wasmtime_wasip2_config_arg (wasi_config, *arg, strlen (*arg)); From cf36a285f9392e455216c458fbc703d88c00b0a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Sun, 21 Sep 2025 18:37:07 +0200 Subject: [PATCH 10/19] wasmtime: properly check wat file extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 49f315f308..ca7f176d10 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -104,7 +104,7 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, // If entrypoint contains a webassembly text format // compile it on the fly and convert to equivalent // binary format. - if (has_suffix (pathname, "wat") > 0) + if (has_suffix (pathname, ".wat") > 0) { wasmtime_error_t *err = wasmtime_wat2wasm ((char *) wasm.data, file_size, &wasm_bytes); if (err != NULL) From 877ca9ac53c5a592e8e309f5cb1a9377ad2457a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Sun, 21 Sep 2025 18:29:02 +0200 Subject: [PATCH 11/19] wasmtime: Add helper for wasm header interpretation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/handler-utils.c | 18 ++++++++++++++++++ src/libcrun/handlers/handler-utils.h | 9 +++++++++ 2 files changed, 27 insertions(+) diff --git a/src/libcrun/handlers/handler-utils.c b/src/libcrun/handlers/handler-utils.c index 608644ec82..7ce121be87 100644 --- a/src/libcrun/handlers/handler-utils.c +++ b/src/libcrun/handlers/handler-utils.c @@ -19,6 +19,7 @@ #define _GNU_SOURCE #include +#include #include "../container.h" #include "../utils.h" #include "handler-utils.h" @@ -69,3 +70,20 @@ wasm_can_handle_container (libcrun_container_t *container, libcrun_error_t *err return 0; } + +wasm_encoding_t +wasm_interpete_header (const char *header) +{ + // Check for the WebAssembly magic bytes + if (strncmp (header, "\0asm", 4)) + return WASM_ENC_INVALID; + + // We don't care for the specific WebAssembly version + // so we only read the value of the `layer` field. + if (header[6] == '\0' && header[7] == '\0') + return WASM_ENC_MODULE; + + // `layer` does not equal 0x00 0x00 so we are working + // with a component. + return WASM_ENC_COMPONENT; +} diff --git a/src/libcrun/handlers/handler-utils.h b/src/libcrun/handlers/handler-utils.h index 98e94d7ba1..f60424ae45 100644 --- a/src/libcrun/handlers/handler-utils.h +++ b/src/libcrun/handlers/handler-utils.h @@ -21,6 +21,15 @@ #include "../container.h" #include +typedef enum +{ + WASM_ENC_INVALID, + WASM_ENC_MODULE, + WASM_ENC_COMPONENT +} wasm_encoding_t; + int wasm_can_handle_container (libcrun_container_t *container, libcrun_error_t *err); +wasm_encoding_t wasm_interpete_header (const char *header); + #endif From d6b977868dee54a828bb45953a1a2a9022aaf6d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Sun, 21 Sep 2025 20:38:14 +0200 Subject: [PATCH 12/19] wasmtime: branch execution path after wasm header interpretation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/handler-utils.c | 11 ++++++++--- src/libcrun/handlers/wasmtime.c | 24 +++++++----------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/libcrun/handlers/handler-utils.c b/src/libcrun/handlers/handler-utils.c index 7ce121be87..406f22aa5c 100644 --- a/src/libcrun/handlers/handler-utils.c +++ b/src/libcrun/handlers/handler-utils.c @@ -75,15 +75,20 @@ wasm_encoding_t wasm_interpete_header (const char *header) { // Check for the WebAssembly magic bytes + // See: https://webassembly.github.io/spec/core/binary/modules.html#binary-module if (strncmp (header, "\0asm", 4)) return WASM_ENC_INVALID; - // We don't care for the specific WebAssembly version - // so we only read the value of the `layer` field. + /* The next four bytes are the WebAssembly version. + We don't care for the specific WebAssembly version + so we only read the value of the `layer` field which + was defined by the component spec. + See: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Binary.md#component-definitions + */ if (header[6] == '\0' && header[7] == '\0') return WASM_ENC_MODULE; - // `layer` does not equal 0x00 0x00 so we are working + // `layer` does not equal `0x00 0x00` so we are working // with a component. return WASM_ENC_COMPONENT; } diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index ca7f176d10..5e65ebb8b3 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -117,26 +117,16 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, wasm = wasm_bytes; } - // Check if it is a valid webassembly module or - // a component. - bool is_wasm_module = true; - wasmtime_error_t *err = wasmtime_module_validate (engine, (uint8_t *) wasm.data, wasm.size); - if (err != NULL) - { - wasmtime_error_message (err, &error_message); - wasmtime_error_delete (err); - - if (strcmp ((char *) error_message.data, "component passed to module validation") != 0) - error (EXIT_FAILURE, 0, "failed to validate module: %.*s", (int) error_message.size, error_message.data); + wasm_encoding_t wasm_enc = wasm_interpete_header (wasm.data); + if (wasm_enc == WASM_ENC_INVALID) + error (EXIT_FAILURE, 0, "invalid wasm binary header"); - err = NULL; - is_wasm_module = false; - } - - if (is_wasm_module) + if (wasm_enc == WASM_ENC_MODULE) libwasmtime_run_module (cookie, argv, engine, &wasm); - else + else if (wasm_enc == WASM_ENC_COMPONENT) libwasmtime_run_component (cookie, argv, engine, &wasm); + else + error (EXIT_FAILURE, 0, "unsupport wasm encoding detected"); exit (EXIT_SUCCESS); } From 49f0f42eca6e4e377e36d87e3d14fc119bea46a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Fri, 26 Sep 2025 22:17:03 +0200 Subject: [PATCH 13/19] wasmtime: fix typo in errmsg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 5e65ebb8b3..7fac06d5df 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -126,7 +126,7 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, else if (wasm_enc == WASM_ENC_COMPONENT) libwasmtime_run_component (cookie, argv, engine, &wasm); else - error (EXIT_FAILURE, 0, "unsupport wasm encoding detected"); + error (EXIT_FAILURE, 0, "unsupported wasm encoding detected"); exit (EXIT_SUCCESS); } From 2170c02665823e623d7f7ca2063532dd152427e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Fri, 26 Sep 2025 22:18:17 +0200 Subject: [PATCH 14/19] wasmtime: remove e flag from fopen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 7fac06d5df..53fbc69c61 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -88,7 +88,7 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, wasm_byte_vec_t wasm; // Load and parse container entrypoint - FILE *file = fopen (pathname, "rbe"); + FILE *file = fopen (pathname, "rb"); if (! file) error (EXIT_FAILURE, 0, "error loading entrypoint"); if (fseek (file, 0L, SEEK_END)) From 5ef89690726b379d86582e289a76c03f98fad80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Wed, 1 Oct 2025 21:12:38 +0200 Subject: [PATCH 15/19] wasmtime: harden wasm_interpret_header func MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/handler-utils.c | 7 +++++-- src/libcrun/handlers/handler-utils.h | 2 +- src/libcrun/handlers/wasmtime.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libcrun/handlers/handler-utils.c b/src/libcrun/handlers/handler-utils.c index 406f22aa5c..676037d9f8 100644 --- a/src/libcrun/handlers/handler-utils.c +++ b/src/libcrun/handlers/handler-utils.c @@ -72,11 +72,14 @@ wasm_can_handle_container (libcrun_container_t *container, libcrun_error_t *err } wasm_encoding_t -wasm_interpete_header (const char *header) +wasm_interpret_header (const char *header, const size_t len) { + if (len < 8) + return WASM_ENC_INVALID; + // Check for the WebAssembly magic bytes // See: https://webassembly.github.io/spec/core/binary/modules.html#binary-module - if (strncmp (header, "\0asm", 4)) + if (memcmp (header, "\0asm", 4)) return WASM_ENC_INVALID; /* The next four bytes are the WebAssembly version. diff --git a/src/libcrun/handlers/handler-utils.h b/src/libcrun/handlers/handler-utils.h index f60424ae45..d0a132b4d0 100644 --- a/src/libcrun/handlers/handler-utils.h +++ b/src/libcrun/handlers/handler-utils.h @@ -30,6 +30,6 @@ typedef enum int wasm_can_handle_container (libcrun_container_t *container, libcrun_error_t *err); -wasm_encoding_t wasm_interpete_header (const char *header); +wasm_encoding_t wasm_interpret_header (const char *header, const size_t len); #endif diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 53fbc69c61..7d51a89b87 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -117,7 +117,7 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, wasm = wasm_bytes; } - wasm_encoding_t wasm_enc = wasm_interpete_header (wasm.data); + wasm_encoding_t wasm_enc = wasm_interpret_header (wasm.data, wasm.size); if (wasm_enc == WASM_ENC_INVALID) error (EXIT_FAILURE, 0, "invalid wasm binary header"); From 9b541eaadba6a6c9ba76e01fde5d1fe412317845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Wed, 1 Oct 2025 21:32:14 +0200 Subject: [PATCH 16/19] wasmtime: avoid NULL pointer after wasm compilation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 7d51a89b87..7c05b4583c 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -243,12 +243,14 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, // Compile wasm modules wasmtime_module_t *module = NULL; err = wasmtime_module_new (engine, (uint8_t *) wasm->data, wasm->size, &module); - if (! module) + if (err != NULL) { wasmtime_error_message (err, &error_message); wasmtime_error_delete (err); error (EXIT_FAILURE, 0, "failed to compile module: %.*s", (int) error_message.size, error_message.data); } + if (module == NULL) + error (EXIT_FAILURE, 0, "internal error: module is NULL"); wasm_byte_vec_delete (wasm); // Init WASI program @@ -422,12 +424,14 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi // Compile wasm component wasmtime_component_t *component = NULL; wasmtime_error_t *err = wasmtime_component_new (engine, (uint8_t *) wasm->data, wasm->size, &component); - if (! component || err != NULL) + if (err != NULL) { wasmtime_error_message (err, &error_message); wasmtime_error_delete (err); error (EXIT_FAILURE, 0, "failed to compile component: %.*s", (int) error_message.size, error_message.data); } + if (component == NULL) + error (EXIT_FAILURE, 0, "internal error: component is NULL"); wasm_byte_vec_delete (wasm); // Set up WASIp2 config From edef23bd073fe640129d1b431f229e2add790f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Wed, 8 Oct 2025 16:24:20 +0200 Subject: [PATCH 17/19] wasmtime: share common symbol loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 91 +++++++++++++++------------------ 1 file changed, 40 insertions(+), 51 deletions(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 7c05b4583c..7ff8f18e45 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -131,6 +131,41 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, exit (EXIT_SUCCESS); } +static void * +libwasmtime_load_symbol (void *cookie, char *const symbol) +{ + void *sym = dlsym (cookie, symbol); + if (sym == NULL) + error (EXIT_FAILURE, 0, "could not find symbol in `libwasmtime.so`: %.*s", (int) strlen (symbol), symbol); + + return sym; +} + +# define WASMTIME_COMMON_SYMBOLS(cookie) \ + void (*wasm_engine_delete) (wasm_engine_t *) \ + = libwasmtime_load_symbol ((cookie), "wasm_engine_delete"); \ + void (*wasm_byte_vec_delete) (wasm_byte_vec_t *) \ + = libwasmtime_load_symbol ((cookie), "wasm_byte_vec_delete"); \ + wasmtime_store_t *(*wasmtime_store_new) (wasm_engine_t * engine, void *data, void (*finalizer) (void *)) \ + = libwasmtime_load_symbol ((cookie), "wasmtime_store_new"); \ + void (*wasmtime_store_delete) (wasmtime_store_t * store) \ + = libwasmtime_load_symbol ((cookie), "wasmtime_store_delete"); \ + wasmtime_context_t *(*wasmtime_store_context) (wasmtime_store_t * store) \ + = libwasmtime_load_symbol ((cookie), "wasmtime_store_context"); \ + void (*wasi_config_inherit_env) (wasi_config_t * config) \ + = libwasmtime_load_symbol ((cookie), "wasi_config_inherit_env"); \ + void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message) \ + = libwasmtime_load_symbol ((cookie), "wasmtime_error_message"); \ + void (*wasmtime_error_delete) (wasmtime_error_t * error) \ + = libwasmtime_load_symbol ((cookie), "wasmtime_error_delete"); \ + bool (*wasi_config_preopen_dir) ( \ + wasi_config_t * config, \ + const char *path, \ + const char *guest_path, \ + wasi_dir_perms dir_perms, \ + wasi_file_perms file_perms) \ + = libwasmtime_load_symbol ((cookie), "wasi_config_preopen_dir"); + static void libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t *wasm) { @@ -139,11 +174,8 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t error_message; // Load needed functions - void (*wasm_engine_delete) (wasm_engine_t *); - void (*wasm_byte_vec_delete) (wasm_byte_vec_t *); + WASMTIME_COMMON_SYMBOLS (cookie) wasi_config_t *(*wasi_config_new) (const char *); - wasmtime_store_t *(*wasmtime_store_new) (wasm_engine_t *engine, void *data, void (*finalizer) (void *)); - wasmtime_context_t *(*wasmtime_store_context) (wasmtime_store_t *store); wasmtime_linker_t *(*wasmtime_linker_new) (wasm_engine_t *engine); wasmtime_error_t *(*wasmtime_linker_define_wasi) (wasmtime_linker_t *linker); wasmtime_error_t *(*wasmtime_module_new) ( @@ -151,8 +183,6 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, const uint8_t *wasm, size_t wasm_len, wasmtime_module_t **ret); - void (*wasi_config_inherit_argv) (wasi_config_t *config); - void (*wasi_config_inherit_env) (wasi_config_t *config); void (*wasi_config_set_argv) (wasi_config_t *config, int argc, const char *argv[]); void (*wasi_config_inherit_stdin) (wasi_config_t *config); void (*wasi_config_inherit_stdout) (wasi_config_t *config); @@ -179,44 +209,25 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, size_t nresults, wasm_trap_t **trap); void (*wasmtime_module_delete) (wasmtime_module_t *m); - void (*wasmtime_store_delete) (wasmtime_store_t *store); - void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message); - void (*wasmtime_error_delete) (wasmtime_error_t *error); - bool (*wasi_config_preopen_dir) ( - wasi_config_t *config, - const char *path, - const char *guest_path, - wasi_dir_perms dir_perms, - wasi_file_perms file_perms); - - wasm_engine_delete = dlsym (cookie, "wasm_engine_delete"); - wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete"); + wasi_config_new = dlsym (cookie, "wasi_config_new"); wasi_config_set_argv = dlsym (cookie, "wasi_config_set_argv"); - wasmtime_store_new = dlsym (cookie, "wasmtime_store_new"); - wasmtime_store_context = dlsym (cookie, "wasmtime_store_context"); wasmtime_linker_new = dlsym (cookie, "wasmtime_linker_new"); wasmtime_linker_define_wasi = dlsym (cookie, "wasmtime_linker_define_wasi"); wasmtime_module_new = dlsym (cookie, "wasmtime_module_new"); - wasi_config_inherit_argv = dlsym (cookie, "wasi_config_inherit_argv"); wasi_config_inherit_stdout = dlsym (cookie, "wasi_config_inherit_stdout"); wasi_config_inherit_stdin = dlsym (cookie, "wasi_config_inherit_stdin"); wasi_config_inherit_stderr = dlsym (cookie, "wasi_config_inherit_stderr"); - wasi_config_inherit_env = dlsym (cookie, "wasi_config_inherit_env"); wasmtime_context_set_wasi = dlsym (cookie, "wasmtime_context_set_wasi"); wasmtime_linker_module = dlsym (cookie, "wasmtime_linker_module"); wasmtime_linker_get_default = dlsym (cookie, "wasmtime_linker_get_default"); wasmtime_func_call = dlsym (cookie, "wasmtime_func_call"); wasmtime_module_delete = dlsym (cookie, "wasmtime_module_delete"); - wasmtime_store_delete = dlsym (cookie, "wasmtime_store_delete"); - wasmtime_error_delete = dlsym (cookie, "wasmtime_error_delete"); - wasmtime_error_message = dlsym (cookie, "wasmtime_error_message"); - wasi_config_preopen_dir = dlsym (cookie, "wasi_config_preopen_dir"); if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL || wasi_config_new == NULL || wasmtime_store_new == NULL || wasmtime_store_context == NULL || wasmtime_linker_new == NULL || wasmtime_linker_define_wasi == NULL - || wasmtime_module_new == NULL || wasi_config_inherit_argv == NULL || wasi_config_inherit_stdout == NULL + || wasmtime_module_new == NULL || wasi_config_inherit_stdout == NULL || wasi_config_inherit_stdin == NULL || wasi_config_inherit_stderr == NULL || wasi_config_inherit_env == NULL || wasmtime_context_set_wasi == NULL || wasmtime_linker_module == NULL || wasmtime_linker_get_default == NULL || wasmtime_func_call == NULL @@ -324,18 +335,13 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasm_byte_vec_t error_message; // Load needed functions - void (*wasm_engine_delete) (wasm_engine_t *); - void (*wasm_byte_vec_delete) (wasm_byte_vec_t *); - wasmtime_store_t *(*wasmtime_store_new) (wasm_engine_t *engine, void *data, void (*finalizer) (void *)); - void (*wasmtime_store_delete) (wasmtime_store_t *store); - wasmtime_context_t *(*wasmtime_store_context) (wasmtime_store_t *store); + WASMTIME_COMMON_SYMBOLS (cookie) wasmtime_error_t *(*wasmtime_component_new) ( const wasm_engine_t *engine, const uint8_t *buf, size_t len, wasmtime_component_t **component_out); wasmtime_wasip2_config_t *(*wasmtime_wasip2_config_new) (void); - void (*wasi_config_inherit_env) (wasi_config_t *config); void (*wasmtime_wasip2_config_inherit_stdin) (wasmtime_wasip2_config_t *config); void (*wasmtime_wasip2_config_inherit_stdout) (wasmtime_wasip2_config_t *config); void (*wasmtime_wasip2_config_inherit_stderr) (wasmtime_wasip2_config_t *config); @@ -369,23 +375,9 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi void (*wasmtime_component_export_index_delete) (wasmtime_component_export_index_t *export_index); void (*wasmtime_component_delete) (wasmtime_component_t *c); void (*wasmtime_component_linker_delete) (wasmtime_component_linker_t *linker); - void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message); - void (*wasmtime_error_delete) (wasmtime_error_t *error); - bool (*wasi_config_preopen_dir) ( - wasi_config_t *config, - const char *path, - const char *guest_path, - wasi_dir_perms dir_perms, - wasi_file_perms file_perms); - - wasm_engine_delete = dlsym (cookie, "wasm_engine_delete"); - wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete"); - wasmtime_store_new = dlsym (cookie, "wasmtime_store_new"); - wasmtime_store_delete = dlsym (cookie, "wasmtime_store_delete"); - wasmtime_store_context = dlsym (cookie, "wasmtime_store_context"); + wasmtime_component_new = dlsym (cookie, "wasmtime_component_new"); wasmtime_wasip2_config_new = dlsym (cookie, "wasmtime_wasip2_config_new"); - wasi_config_inherit_env = dlsym (cookie, "wasi_config_inherit_env"); wasmtime_wasip2_config_inherit_stdin = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdin"); wasmtime_wasip2_config_inherit_stdout = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdout"); wasmtime_wasip2_config_inherit_stderr = dlsym (cookie, "wasmtime_wasip2_config_inherit_stderr"); @@ -400,9 +392,6 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi wasmtime_component_export_index_delete = dlsym (cookie, "wasmtime_component_export_index_delete"); wasmtime_component_delete = dlsym (cookie, "wasmtime_component_delete"); wasmtime_component_linker_delete = dlsym (cookie, "wasmtime_component_linker_delete"); - wasmtime_error_message = dlsym (cookie, "wasmtime_error_message"); - wasmtime_error_delete = dlsym (cookie, "wasmtime_error_delete"); - wasi_config_preopen_dir = dlsym (cookie, "wasi_config_preopen_dir"); if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL || wasmtime_store_new == NULL || wasmtime_store_delete == NULL || wasmtime_store_context == NULL || wasmtime_component_new == NULL From 97b21027babeb91550d414ae2ca2fafec0adffaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Wed, 8 Oct 2025 16:56:19 +0200 Subject: [PATCH 18/19] wasmtime: use symbol loading helper everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 180 +++++++++++++------------------- 1 file changed, 74 insertions(+), 106 deletions(-) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index 7ff8f18e45..c73bd76391 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -44,6 +44,9 @@ #endif #if HAVE_DLOPEN && HAVE_WASMTIME +static void * +libwasmtime_load_symbol (void *cookie, char *const symbol); + static void libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t *wasm); @@ -56,30 +59,19 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, { wasm_byte_vec_t error_message; wasm_byte_vec_t wasm_bytes; - wasm_engine_t *(*wasm_engine_new) (); - wasmtime_error_t *(*wasmtime_wat2wasm) (const char *wat, size_t wat_len, wasm_byte_vec_t *out); - void (*wasm_byte_vec_new_uninitialized) (wasm_byte_vec_t *, size_t); - void (*wasm_byte_vec_delete) (wasm_byte_vec_t *); - wasmtime_error_t *(*wasmtime_module_validate) (wasm_engine_t *engine, const uint8_t *wasm, size_t wasm_len); - void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message); - void (*wasmtime_error_delete) (wasmtime_error_t *error); - - wasmtime_wat2wasm = dlsym (cookie, "wasmtime_wat2wasm"); - wasm_engine_new = dlsym (cookie, "wasm_engine_new"); - wasm_byte_vec_new_uninitialized = dlsym (cookie, "wasm_byte_vec_new_uninitialized"); - wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete"); - wasmtime_module_validate = dlsym (cookie, "wasmtime_module_validate"); - wasmtime_error_delete = dlsym (cookie, "wasmtime_error_delete"); - wasmtime_error_message = dlsym (cookie, "wasmtime_error_message"); - - if (wasmtime_wat2wasm == NULL - || wasm_engine_new == NULL - || wasm_byte_vec_new_uninitialized == NULL - || wasm_byte_vec_delete == NULL - || wasmtime_module_validate == NULL - || wasmtime_error_delete == NULL - || wasmtime_error_message == NULL) - error (EXIT_FAILURE, 0, "could not find symbol in `libwasmtime.so`"); + + wasm_engine_t *(*wasm_engine_new) () + = libwasmtime_load_symbol (cookie, "wasm_engine_new"); + wasmtime_error_t *(*wasmtime_wat2wasm) (const char *wat, size_t wat_len, wasm_byte_vec_t *out) + = libwasmtime_load_symbol (cookie, "wasmtime_wat2wasm"); + void (*wasm_byte_vec_new_uninitialized) (wasm_byte_vec_t *, size_t) + = libwasmtime_load_symbol (cookie, "wasm_byte_vec_new_uninitialized"); + void (*wasm_byte_vec_delete) (wasm_byte_vec_t *) + = libwasmtime_load_symbol (cookie, "wasm_byte_vec_delete"); + void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message) + = libwasmtime_load_symbol (cookie, "wasmtime_error_message"); + void (*wasmtime_error_delete) (wasmtime_error_t *error) + = libwasmtime_load_symbol (cookie, "wasmtime_error_delete"); // Set up wasmtime context wasm_engine_t *engine = wasm_engine_new (); @@ -175,31 +167,42 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, // Load needed functions WASMTIME_COMMON_SYMBOLS (cookie) - wasi_config_t *(*wasi_config_new) (const char *); - wasmtime_linker_t *(*wasmtime_linker_new) (wasm_engine_t *engine); - wasmtime_error_t *(*wasmtime_linker_define_wasi) (wasmtime_linker_t *linker); + wasi_config_t *(*wasi_config_new) (const char *) + = libwasmtime_load_symbol (cookie, "wasi_config_new"); + wasmtime_linker_t *(*wasmtime_linker_new) (wasm_engine_t *engine) + = libwasmtime_load_symbol (cookie, "wasmtime_linker_new"); + wasmtime_error_t *(*wasmtime_linker_define_wasi) (wasmtime_linker_t *linker) + = libwasmtime_load_symbol (cookie, "wasmtime_linker_define_wasi"); wasmtime_error_t *(*wasmtime_module_new) ( wasm_engine_t *engine, const uint8_t *wasm, size_t wasm_len, - wasmtime_module_t **ret); - void (*wasi_config_set_argv) (wasi_config_t *config, int argc, const char *argv[]); - void (*wasi_config_inherit_stdin) (wasi_config_t *config); - void (*wasi_config_inherit_stdout) (wasi_config_t *config); - void (*wasi_config_inherit_stderr) (wasi_config_t *config); - wasmtime_error_t *(*wasmtime_context_set_wasi) (wasmtime_context_t *context, wasi_config_t *wasi); + wasmtime_module_t **ret) + = libwasmtime_load_symbol (cookie, "wasmtime_module_new"); + void (*wasi_config_set_argv) (wasi_config_t *config, int argc, const char *argv[]) + = libwasmtime_load_symbol (cookie, "wasi_config_set_argv"); + void (*wasi_config_inherit_stdin) (wasi_config_t *config) + = libwasmtime_load_symbol (cookie, "wasi_config_inherit_stdin"); + void (*wasi_config_inherit_stdout) (wasi_config_t *config) + = libwasmtime_load_symbol (cookie, "wasi_config_inherit_stdout"); + void (*wasi_config_inherit_stderr) (wasi_config_t *config) + = libwasmtime_load_symbol (cookie, "wasi_config_inherit_stderr"); + wasmtime_error_t *(*wasmtime_context_set_wasi) (wasmtime_context_t *context, wasi_config_t *wasi) + = libwasmtime_load_symbol (cookie, "wasmtime_context_set_wasi"); wasmtime_error_t *(*wasmtime_linker_module) ( wasmtime_linker_t *linker, wasmtime_context_t *store, const char *name, size_t name_len, - const wasmtime_module_t *module); + const wasmtime_module_t *module) + = libwasmtime_load_symbol (cookie, "wasmtime_linker_module"); wasmtime_error_t *(*wasmtime_linker_get_default) ( const wasmtime_linker_t *linker, wasmtime_context_t *store, const char *name, size_t name_len, - wasmtime_func_t *func); + wasmtime_func_t *func) + = libwasmtime_load_symbol (cookie, "wasmtime_linker_get_default"); wasmtime_error_t *(*wasmtime_func_call) ( wasmtime_context_t *store, const wasmtime_func_t *func, @@ -207,33 +210,10 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine, size_t nargs, wasmtime_val_t *results, size_t nresults, - wasm_trap_t **trap); - void (*wasmtime_module_delete) (wasmtime_module_t *m); - - wasi_config_new = dlsym (cookie, "wasi_config_new"); - wasi_config_set_argv = dlsym (cookie, "wasi_config_set_argv"); - wasmtime_linker_new = dlsym (cookie, "wasmtime_linker_new"); - wasmtime_linker_define_wasi = dlsym (cookie, "wasmtime_linker_define_wasi"); - wasmtime_module_new = dlsym (cookie, "wasmtime_module_new"); - wasi_config_inherit_stdout = dlsym (cookie, "wasi_config_inherit_stdout"); - wasi_config_inherit_stdin = dlsym (cookie, "wasi_config_inherit_stdin"); - wasi_config_inherit_stderr = dlsym (cookie, "wasi_config_inherit_stderr"); - wasmtime_context_set_wasi = dlsym (cookie, "wasmtime_context_set_wasi"); - wasmtime_linker_module = dlsym (cookie, "wasmtime_linker_module"); - wasmtime_linker_get_default = dlsym (cookie, "wasmtime_linker_get_default"); - wasmtime_func_call = dlsym (cookie, "wasmtime_func_call"); - wasmtime_module_delete = dlsym (cookie, "wasmtime_module_delete"); - - if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL - || wasi_config_new == NULL || wasmtime_store_new == NULL - || wasmtime_store_context == NULL || wasmtime_linker_new == NULL || wasmtime_linker_define_wasi == NULL - || wasmtime_module_new == NULL || wasi_config_inherit_stdout == NULL - || wasi_config_inherit_stdin == NULL || wasi_config_inherit_stderr == NULL - || wasi_config_inherit_env == NULL || wasmtime_context_set_wasi == NULL - || wasmtime_linker_module == NULL || wasmtime_linker_get_default == NULL || wasmtime_func_call == NULL - || wasmtime_module_delete == NULL || wasmtime_store_delete == NULL || wasi_config_set_argv == NULL - || wasmtime_error_delete == NULL || wasmtime_error_message == NULL || wasi_config_preopen_dir == NULL) - error (EXIT_FAILURE, 0, "could not find symbol in `libwasmtime.so`"); + wasm_trap_t **trap) + = libwasmtime_load_symbol (cookie, "wasmtime_func_call"); + void (*wasmtime_module_delete) (wasmtime_module_t *m) + = libwasmtime_load_symbol (cookie, "wasmtime_module_delete"); // Set up wasmtime context wasmtime_store_t *store = wasmtime_store_new (engine, NULL, NULL); @@ -340,69 +320,57 @@ libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engi const wasm_engine_t *engine, const uint8_t *buf, size_t len, - wasmtime_component_t **component_out); - wasmtime_wasip2_config_t *(*wasmtime_wasip2_config_new) (void); - void (*wasmtime_wasip2_config_inherit_stdin) (wasmtime_wasip2_config_t *config); - void (*wasmtime_wasip2_config_inherit_stdout) (wasmtime_wasip2_config_t *config); - void (*wasmtime_wasip2_config_inherit_stderr) (wasmtime_wasip2_config_t *config); - void (*wasmtime_wasip2_config_arg) (wasmtime_wasip2_config_t *config, const char *arg, size_t arg_len); - void (*wasmtime_context_set_wasip2) (wasmtime_context_t *context, wasmtime_wasip2_config_t *config); - wasmtime_component_linker_t *(*wasmtime_component_linker_new) (wasm_engine_t *engine); - wasmtime_error_t *(*wasmtime_component_linker_add_wasip2) (wasmtime_component_linker_t *linker); + wasmtime_component_t **component_out) + = libwasmtime_load_symbol (cookie, "wasmtime_component_new"); + wasmtime_wasip2_config_t *(*wasmtime_wasip2_config_new) (void) + = libwasmtime_load_symbol (cookie, "wasmtime_wasip2_config_new"); + void (*wasmtime_wasip2_config_inherit_stdin) (wasmtime_wasip2_config_t *config) + = libwasmtime_load_symbol (cookie, "wasmtime_wasip2_config_inherit_stdin"); + void (*wasmtime_wasip2_config_inherit_stdout) (wasmtime_wasip2_config_t *config) + = libwasmtime_load_symbol (cookie, "wasmtime_wasip2_config_inherit_stdout"); + void (*wasmtime_wasip2_config_inherit_stderr) (wasmtime_wasip2_config_t *config) + = libwasmtime_load_symbol (cookie, "wasmtime_wasip2_config_inherit_stderr"); + void (*wasmtime_wasip2_config_arg) (wasmtime_wasip2_config_t *config, const char *arg, size_t arg_len) + = libwasmtime_load_symbol (cookie, "wasmtime_wasip2_config_arg"); + void (*wasmtime_context_set_wasip2) (wasmtime_context_t *context, wasmtime_wasip2_config_t *config) + = libwasmtime_load_symbol (cookie, "wasmtime_context_set_wasip2"); + wasmtime_component_linker_t *(*wasmtime_component_linker_new) (wasm_engine_t *engine) + = libwasmtime_load_symbol (cookie, "wasmtime_component_linker_new"); + wasmtime_error_t *(*wasmtime_component_linker_add_wasip2) (wasmtime_component_linker_t *linker) + = libwasmtime_load_symbol (cookie, "wasmtime_component_linker_add_wasip2"); wasmtime_error_t *(*wasmtime_component_linker_instantiate) ( const wasmtime_component_linker_t *linker, wasmtime_context_t *context, const wasmtime_component_t *component, - wasmtime_component_instance_t *instance_out); + wasmtime_component_instance_t *instance_out) + = libwasmtime_load_symbol (cookie, "wasmtime_component_linker_instantiate"); wasmtime_component_export_index_t *(*wasmtime_component_instance_get_export_index) ( const wasmtime_component_instance_t *instance, wasmtime_context_t *context, const wasmtime_component_export_index_t *instance_export_index, const char *name, - size_t name_len); + size_t name_len) + = libwasmtime_load_symbol (cookie, "wasmtime_component_instance_get_export_index"); bool (*wasmtime_component_instance_get_func) ( const wasmtime_component_instance_t *instance, wasmtime_context_t *context, const wasmtime_component_export_index_t *export_index, - wasmtime_component_func_t *func_out); + wasmtime_component_func_t *func_out) + = libwasmtime_load_symbol (cookie, "wasmtime_component_instance_get_func"); wasmtime_error_t *(*wasmtime_component_func_call) ( const wasmtime_component_func_t *func, wasmtime_context_t *context, const wasmtime_component_val_t *args, size_t args_size, wasmtime_component_val_t *results, - size_t results_size); - void (*wasmtime_component_export_index_delete) (wasmtime_component_export_index_t *export_index); - void (*wasmtime_component_delete) (wasmtime_component_t *c); - void (*wasmtime_component_linker_delete) (wasmtime_component_linker_t *linker); - - wasmtime_component_new = dlsym (cookie, "wasmtime_component_new"); - wasmtime_wasip2_config_new = dlsym (cookie, "wasmtime_wasip2_config_new"); - wasmtime_wasip2_config_inherit_stdin = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdin"); - wasmtime_wasip2_config_inherit_stdout = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdout"); - wasmtime_wasip2_config_inherit_stderr = dlsym (cookie, "wasmtime_wasip2_config_inherit_stderr"); - wasmtime_wasip2_config_arg = dlsym (cookie, "wasmtime_wasip2_config_arg"); - wasmtime_context_set_wasip2 = dlsym (cookie, "wasmtime_context_set_wasip2"); - wasmtime_component_linker_new = dlsym (cookie, "wasmtime_component_linker_new"); - wasmtime_component_linker_add_wasip2 = dlsym (cookie, "wasmtime_component_linker_add_wasip2"); - wasmtime_component_linker_instantiate = dlsym (cookie, "wasmtime_component_linker_instantiate"); - wasmtime_component_instance_get_export_index = dlsym (cookie, "wasmtime_component_instance_get_export_index"); - wasmtime_component_instance_get_func = dlsym (cookie, "wasmtime_component_instance_get_func"); - wasmtime_component_func_call = dlsym (cookie, "wasmtime_component_func_call"); - wasmtime_component_export_index_delete = dlsym (cookie, "wasmtime_component_export_index_delete"); - wasmtime_component_delete = dlsym (cookie, "wasmtime_component_delete"); - wasmtime_component_linker_delete = dlsym (cookie, "wasmtime_component_linker_delete"); - - if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL || wasmtime_store_new == NULL - || wasmtime_store_delete == NULL || wasmtime_store_context == NULL || wasmtime_component_new == NULL - || wasmtime_wasip2_config_new == NULL || wasi_config_inherit_env == NULL || wasmtime_wasip2_config_inherit_stdin == NULL - || wasmtime_wasip2_config_inherit_stdout == NULL || wasmtime_wasip2_config_inherit_stderr == NULL || wasmtime_wasip2_config_arg == NULL - || wasmtime_context_set_wasip2 == NULL || wasmtime_component_linker_new == NULL || wasmtime_component_linker_add_wasip2 == NULL - || wasmtime_component_linker_instantiate == NULL || wasmtime_component_instance_get_export_index == NULL - || wasmtime_component_instance_get_func == NULL || wasmtime_component_func_call == NULL || wasmtime_component_export_index_delete == NULL - || wasmtime_component_delete == NULL || wasmtime_component_linker_delete == NULL || wasmtime_error_message == NULL - || wasmtime_error_delete == NULL || wasi_config_preopen_dir == NULL) - error (EXIT_FAILURE, 0, "could not find symbol in `libwasmtime.so`"); + size_t results_size) + = libwasmtime_load_symbol (cookie, "wasmtime_component_func_call"); + void (*wasmtime_component_export_index_delete) (wasmtime_component_export_index_t *export_index) + = libwasmtime_load_symbol (cookie, "wasmtime_component_export_index_delete"); + void (*wasmtime_component_delete) (wasmtime_component_t *c) + = libwasmtime_load_symbol (cookie, "wasmtime_component_delete"); + void (*wasmtime_component_linker_delete) (wasmtime_component_linker_t *linker) + = libwasmtime_load_symbol (cookie, "wasmtime_component_linker_delete"); // Set up wasmtime context wasmtime_store_t *store = wasmtime_store_new (engine, NULL, NULL); From d2f793b3f71f908286dfac08674c97591b998936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20H=C3=BCter?= Date: Fri, 10 Oct 2025 16:02:14 +0200 Subject: [PATCH 19/19] wasmtime: ftell error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Hüter --- src/libcrun/handlers/wasmtime.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcrun/handlers/wasmtime.c b/src/libcrun/handlers/wasmtime.c index c73bd76391..9a31288f6e 100644 --- a/src/libcrun/handlers/wasmtime.c +++ b/src/libcrun/handlers/wasmtime.c @@ -86,6 +86,8 @@ libwasmtime_exec (void *cookie, libcrun_container_t *container arg_unused, if (fseek (file, 0L, SEEK_END)) error (EXIT_FAILURE, 0, "error fully loading entrypoint"); size_t file_size = ftell (file); + if (file_size == (size_t) -1L) + error (EXIT_FAILURE, 0, "error getting entrypoint size"); wasm_byte_vec_new_uninitialized (&wasm, file_size); if (fseek (file, 0L, SEEK_SET)) error (EXIT_FAILURE, 0, "error resetting entrypoint");