Skip to content
This repository has been archived by the owner on Sep 12, 2023. It is now read-only.

Commit

Permalink
Add wasmedge support
Browse files Browse the repository at this point in the history
Signed-off-by: Shen-Ta Hsieh <beststeve@secondstate.io>
  • Loading branch information
ibmibmibm committed Sep 6, 2021
1 parent 139dc69 commit 060b275
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 0 deletions.
5 changes: 5 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ AS_IF([test "x$enable_dl" != "xno"], [
dnl include support for libkrun (EXPERIMENTAL)
AC_ARG_WITH([libkrun], AS_HELP_STRING([--with-libkrun], [build with libkrun support]))
AS_IF([test "x$with_libkrun" = "xyes"], AC_CHECK_HEADERS([libkrun.h], AC_DEFINE([HAVE_LIBKRUN], 1, [Define if libkrun is available]), [AC_MSG_ERROR([*** Missing libkrun headers])]))

dnl include support for wasmedge (EXPERIMENTAL)
AC_ARG_WITH([wasmedge], AS_HELP_STRING([--with-wasmedge], [build with WasmEdge support]))
AS_IF([test "x$with_wasmedge" = "xyes"], AC_CHECK_HEADERS([wasmedge.h], AC_DEFINE([HAVE_WASMEDGE], 1, [Define if WasmEdge is available]), [AC_MSG_ERROR([*** Missing wasmedge headers])]))

dnl libseccomp
AC_ARG_ENABLE([seccomp],
AS_HELP_STRING([--disable-seccomp], [Ignore libseccomp and disable support]))
Expand Down
137 changes: 137 additions & 0 deletions src/libcrun/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
# include <libkrun.h>
#endif

#ifdef HAVE_WASMEDGE
# include <wasmedge.h>
#endif

#ifdef HAVE_SYSTEMD
# include <systemd/sd-daemon.h>
#endif
Expand Down Expand Up @@ -88,6 +92,11 @@ struct container_entrypoint_s
execve. */
int (*exec_func) (void *container, void *arg, const char *pathname, char *const argv[]);
void *exec_func_arg;

#if HAVE_DLOPEN && HAVE_WASMEDGE
/* wasmedge library */
void *wasmedge_handle;
#endif
};

struct sync_socket_message_s
Expand Down Expand Up @@ -813,6 +822,102 @@ libkrun_do_exec (void *container, void *arg, const char *pathname, char *const a
}
#endif

#if HAVE_DLOPEN && HAVE_WASMEDGE
static int
libwasmedge_do_exec (void *container, void *handle, const char *pathname, char *const argv[])
{
runtime_spec_schema_config_schema *def = ((libcrun_container_t *) container)->container_def;
WasmEdge_ConfigureContext *(*WasmEdge_ConfigureCreate) (void);
void (*WasmEdge_ConfigureDelete) (WasmEdge_ConfigureContext * Cxt);
void (*WasmEdge_ConfigureAddProposal) (WasmEdge_ConfigureContext * Cxt, const enum WasmEdge_Proposal Prop);
void (*WasmEdge_ConfigureAddHostRegistration) (WasmEdge_ConfigureContext * Cxt, enum WasmEdge_HostRegistration Host);
WasmEdge_VMContext *(*WasmEdge_VMCreate) (const WasmEdge_ConfigureContext *ConfCxt, WasmEdge_StoreContext *StoreCxt);
void (*WasmEdge_VMDelete) (WasmEdge_VMContext * Cxt);
WasmEdge_Result (*WasmEdge_VMRegisterModuleFromFile) (WasmEdge_VMContext * Cxt, WasmEdge_String ModuleName, const char *Path);
WasmEdge_ImportObjectContext *(*WasmEdge_VMGetImportModuleContext) (WasmEdge_VMContext * Cxt, const enum WasmEdge_HostRegistration Reg);
void (*WasmEdge_ImportObjectInitWASI) (WasmEdge_ImportObjectContext * Cxt, const char *const *Args, const uint32_t ArgLen, const char *const *Envs, const uint32_t EnvLen, const char *const *Dirs, const uint32_t DirLen, const char *const *Preopens, const uint32_t PreopenLen);
void (*WasmEdge_ImportObjectInitWasmEdgeProcess) (WasmEdge_ImportObjectContext * Cxt, const char *const *AllowedCmds, const uint32_t CmdsLen, const bool AllowAll);
WasmEdge_Result (*WasmEdge_VMRunWasmFromFile) (WasmEdge_VMContext * Cxt, const char *Path, const WasmEdge_String FuncName, const WasmEdge_Value *Params, const uint32_t ParamLen, WasmEdge_Value *Returns, const uint32_t ReturnLen);
bool (*WasmEdge_ResultOK) (const WasmEdge_Result Res);
WasmEdge_String (*WasmEdge_StringCreateByCString) (const char *Str);

WasmEdge_ConfigureCreate = dlsym (handle, "WasmEdge_ConfigureCreate");
WasmEdge_ConfigureDelete = dlsym (handle, "WasmEdge_ConfigureDelete");
WasmEdge_ConfigureAddProposal = dlsym (handle, "WasmEdge_ConfigureAddProposal");
WasmEdge_ConfigureAddHostRegistration = dlsym (handle, "WasmEdge_ConfigureAddHostRegistration");
WasmEdge_VMCreate = dlsym (handle, "WasmEdge_VMCreate");
WasmEdge_VMDelete = dlsym (handle, "WasmEdge_VMDelete");
WasmEdge_VMRegisterModuleFromFile = dlsym (handle, "WasmEdge_VMRegisterModuleFromFile");
WasmEdge_VMGetImportModuleContext = dlsym (handle, "WasmEdge_VMGetImportModuleContext");
WasmEdge_ImportObjectInitWASI = dlsym (handle, "WasmEdge_ImportObjectInitWASI");
WasmEdge_ImportObjectInitWasmEdgeProcess = dlsym (handle, "WasmEdge_ImportObjectInitWasmEdgeProcess");
WasmEdge_VMRunWasmFromFile = dlsym (handle, "WasmEdge_VMRunWasmFromFile");
WasmEdge_ResultOK = dlsym (handle, "WasmEdge_ResultOK");
WasmEdge_StringCreateByCString = dlsym (handle, "WasmEdge_StringCreateByCString");
if (WasmEdge_ConfigureCreate == NULL || WasmEdge_ConfigureDelete == NULL || WasmEdge_ConfigureAddProposal == NULL || WasmEdge_ConfigureAddHostRegistration == NULL || WasmEdge_VMCreate == NULL || WasmEdge_VMDelete == NULL || WasmEdge_VMRegisterModuleFromFile == NULL || WasmEdge_VMGetImportModuleContext == NULL || WasmEdge_ImportObjectInitWASI == NULL || WasmEdge_ImportObjectInitWasmEdgeProcess == NULL || WasmEdge_VMRunWasmFromFile == NULL || WasmEdge_ResultOK == NULL || WasmEdge_StringCreateByCString == NULL)
{
fprintf (stderr, "could not find symbol in `libwasmedge.so`");
dlclose (handle);
return -1;
}

WasmEdge_ConfigureContext *configure = WasmEdge_ConfigureCreate ();
if (UNLIKELY (configure == NULL))
error (EXIT_FAILURE, 0, "could not create wasmedge configure");

WasmEdge_ConfigureAddProposal (configure, WasmEdge_Proposal_BulkMemoryOperations);
WasmEdge_ConfigureAddProposal (configure, WasmEdge_Proposal_ReferenceTypes);
WasmEdge_ConfigureAddProposal (configure, WasmEdge_Proposal_SIMD);
WasmEdge_ConfigureAddHostRegistration (configure, WasmEdge_HostRegistration_Wasi);
WasmEdge_ConfigureAddHostRegistration (configure, WasmEdge_HostRegistration_WasmEdge_Process);

WasmEdge_VMContext *vm = WasmEdge_VMCreate (configure, NULL);
if (UNLIKELY (vm == NULL))
{
WasmEdge_ConfigureDelete (configure);
error (EXIT_FAILURE, 0, "could not create wasmedge vm");
}

WasmEdge_ImportObjectContext *wasi_module = WasmEdge_VMGetImportModuleContext (vm, WasmEdge_HostRegistration_Wasi);
if (UNLIKELY (wasi_module == NULL))
{
WasmEdge_VMDelete (vm);
WasmEdge_ConfigureDelete (configure);
error (EXIT_FAILURE, 0, "could not get wasmedge wasi module context");
}

WasmEdge_ImportObjectContext *proc_module = WasmEdge_VMGetImportModuleContext (vm, WasmEdge_HostRegistration_WasmEdge_Process);
if (UNLIKELY (proc_module == NULL))
{
WasmEdge_VMDelete (vm);
WasmEdge_ConfigureDelete (configure);
error (EXIT_FAILURE, 0, "could not get wasmedge process module context");
}

uint32_t argn = 0;
for (char *const *arg = argv; *arg != NULL; ++arg, ++argn)
;

const char *dirs[1] = { "/:/" };
WasmEdge_ImportObjectInitWASI (wasi_module, (const char *const *) &argv[0], argn, NULL, 0, dirs, 1, NULL, 0);

WasmEdge_ImportObjectInitWasmEdgeProcess (proc_module, NULL, 0, true);

WasmEdge_Result result = WasmEdge_VMRunWasmFromFile (vm, pathname, WasmEdge_StringCreateByCString ("_start"), NULL, 0, NULL, 0);

if (UNLIKELY (! WasmEdge_ResultOK (result)))
{
WasmEdge_VMDelete (vm);
WasmEdge_ConfigureDelete (configure);
error (EXIT_FAILURE, 0, "could not set krun executable");
}

WasmEdge_VMDelete (vm);
WasmEdge_ConfigureDelete (configure);
return 0;
}
#endif

static int
libcrun_configure_libkrun (struct container_entrypoint_s *args, libcrun_error_t *err)
{
Expand All @@ -835,9 +940,33 @@ libcrun_configure_libkrun (struct container_entrypoint_s *args, libcrun_error_t
#endif
}

#if HAVE_DLOPEN && HAVE_WASMEDGE
static int
libcrun_configure_libwasmedge (struct container_entrypoint_s *args, libcrun_error_t *err)
{
void *handle;

handle = dlopen ("libwasmedge_c.so", RTLD_NOW);
if (handle == NULL)
return crun_make_error (err, 0, "could not load `libwasmedge_c.so`: %s", dlerror ());

args->wasmedge_handle = handle;

return 0;
}
#endif

static int
libcrun_configure_handler (struct container_entrypoint_s *args, libcrun_error_t *err)
{
#if HAVE_DLOPEN && HAVE_WASMEDGE
int ret = libcrun_configure_libwasmedge (args, err);
if (UNLIKELY (ret < 0))
{
return ret;
}
#endif

const char *annotation;
annotation = find_annotation (args->container, "run.oci.handler");

Expand Down Expand Up @@ -1469,6 +1598,14 @@ container_init (void *args, char *notify_socket, int sync_socket, libcrun_error_
(void) lseek (2, 0, SEEK_END);
}

#if HAVE_DLOPEN && HAVE_WASMEDGE
if (has_postfix (exec_path, ".wasm"))
{
ret = libwasmedge_do_exec (entrypoint_args->container, entrypoint_args->wasmedge_handle, exec_path, def->process->args);
_exit (ret);
}
#endif

if (entrypoint_args->exec_func)
{
ret = entrypoint_args->exec_func (entrypoint_args->container, entrypoint_args->exec_func_arg, exec_path,
Expand Down
8 changes: 8 additions & 0 deletions src/libcrun/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,14 @@ has_prefix (const char *str, const char *prefix)
return strlen (str) >= prefix_len && memcmp (str, prefix, prefix_len) == 0;
}

int
has_postfix (const char *str, const char *postfix)
{
size_t postfix_len = strlen (postfix);
size_t str_len = strlen (str);
return str_len >= postfix_len && memcmp (str + (str_len - postfix_len), postfix, postfix_len) == 0;
}

static int
check_access (const char *path)
{
Expand Down
2 changes: 2 additions & 0 deletions src/libcrun/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ int parse_json_file (yajl_val *out, const char *jsondata, struct parser_context

int has_prefix (const char *str, const char *prefix);

int has_postfix (const char *str, const char *postfix);

const char *find_executable (const char *executable_path, const char *cwd);

int copy_recursive_fd_to_fd (int srcfd, int destfd, const char *srcname, const char *destname, libcrun_error_t *err);
Expand Down

0 comments on commit 060b275

Please sign in to comment.