summaryrefslogtreecommitdiffhomepage
path: root/src/wasm
diff options
context:
space:
mode:
authorAndrew Clayton <a.clayton@nginx.com>2023-08-09 18:22:46 +0100
committerAndrew Clayton <a.clayton@nginx.com>2023-08-17 13:09:49 +0100
commit47ff51009fa05d83bb67cd5db16829ab4c0081d7 (patch)
tree48066be1f1bd013314fcb2ebb23422146cf9f492 /src/wasm
parente99854afdf555678df5af149e53659c5b30a2f6d (diff)
downloadunit-47ff51009fa05d83bb67cd5db16829ab4c0081d7.tar.gz
unit-47ff51009fa05d83bb67cd5db16829ab4c0081d7.tar.bz2
Wasm: Add support for directory access.
Due to the sandboxed nature of WebAssembly, by default WASM modules don't have any access to the underlying filesystem. There is however a capabilities based mechanism[0] for allowing such access. This adds a config option to the 'wasm' application type; 'access.filesystem' which takes an array of directory paths that are then made available to the WASM module. This access works recursively, i.e everything under a specific path is allowed access to. Example config might look like "access" { "filesystem": [ "/tmp", "/var/tmp" ] } The actual mechanism used allows directories to be mapped differently in the guest. But at the moment we don't support that and just map say /tmp to /tmp. This can be revisited if it's something users clamour for. Network sockets are another resource that may be controlled in this manner, for example there is a wasi_config_preopen_socket() function, however this requires the runtime to open the network socket then effectively pass this through to the guest. This is something that can be revisited in the future if users desire it. [0]: <https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-capabilities.md> Reviewed-by: Alejandro Colomar <alx@nginx.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/nxt_rt_wasmtime.c5
-rw-r--r--src/wasm/nxt_wasm.c40
-rw-r--r--src/wasm/nxt_wasm.h2
3 files changed, 46 insertions, 1 deletions
diff --git a/src/wasm/nxt_rt_wasmtime.c b/src/wasm/nxt_rt_wasmtime.c
index 07a6165a..99786b89 100644
--- a/src/wasm/nxt_rt_wasmtime.c
+++ b/src/wasm/nxt_rt_wasmtime.c
@@ -247,6 +247,7 @@ nxt_wasmtime_get_function_exports(nxt_wasm_ctx_t *ctx)
static int
nxt_wasmtime_wasi_init(const nxt_wasm_ctx_t *ctx)
{
+ char **dir;
wasi_config_t *wasi_config;
wasmtime_error_t *error;
nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx;
@@ -258,6 +259,10 @@ nxt_wasmtime_wasi_init(const nxt_wasm_ctx_t *ctx)
wasi_config_inherit_stdout(wasi_config);
wasi_config_inherit_stderr(wasi_config);
+ for (dir = ctx->dirs; dir != NULL && *dir != NULL; dir++) {
+ wasi_config_preopen_dir(wasi_config, *dir, *dir);
+ }
+
error = wasmtime_context_set_wasi(rt_ctx->ctx, wasi_config);
if (error != NULL) {
nxt_wasmtime_err_msg(error, NULL, "failed to instantiate WASI");
diff --git a/src/wasm/nxt_wasm.c b/src/wasm/nxt_wasm.c
index d96668ad..45a40b4b 100644
--- a/src/wasm/nxt_wasm.c
+++ b/src/wasm/nxt_wasm.c
@@ -204,6 +204,15 @@ nxt_wasm_start(nxt_task_t *task, nxt_process_data_t *data)
nxt_unit_done(unit_ctx);
NXT_WASM_DO_HOOK(NXT_WASM_FH_MODULE_END);
+ if (nxt_wasm_ctx.dirs != NULL) {
+ char **p;
+
+ for (p = nxt_wasm_ctx.dirs; *p != NULL; p++) {
+ nxt_free(*p);
+ }
+ nxt_free(nxt_wasm_ctx.dirs);
+ }
+
nxt_wops->destroy(&nxt_wasm_ctx);
exit(EXIT_SUCCESS);
@@ -214,9 +223,11 @@ static nxt_int_t
nxt_wasm_setup(nxt_task_t *task, nxt_process_t *process,
nxt_common_app_conf_t *conf)
{
- int err;
+ int n, i, err;
+ nxt_conf_value_t *dirs = NULL;
nxt_wasm_app_conf_t *c;
nxt_wasm_func_handler_t *fh;
+ static nxt_str_t filesystem_str = nxt_string("filesystem");
c = &conf->u.wasm;
@@ -237,6 +248,33 @@ nxt_wasm_setup(nxt_task_t *task, nxt_process_t *process,
fh[NXT_WASM_FH_REQUEST_END].func_name = c->request_end_handler;
fh[NXT_WASM_FH_RESPONSE_END].func_name = c->response_end_handler;
+ /* Get any directories to pass through to the WASM module */
+ if (c->access != NULL) {
+ dirs = nxt_conf_get_object_member(c->access, &filesystem_str, NULL);
+ }
+
+ n = (dirs != NULL) ? nxt_conf_object_members_count(dirs) : 0;
+ if (n == 0) {
+ goto out_init;
+ }
+
+ nxt_wasm_ctx.dirs = nxt_zalloc((n + 1) * sizeof(char *));
+ if (nxt_slow_path(nxt_wasm_ctx.dirs == NULL)) {
+ return NXT_ERROR;
+ }
+
+ for (i = 0; i < n; i++) {
+ nxt_str_t str;
+ nxt_conf_value_t *value;
+
+ value = nxt_conf_get_array_element(dirs, i);
+ nxt_conf_get_string(value, &str);
+
+ nxt_wasm_ctx.dirs[i] = nxt_zalloc(str.length + 1);
+ memcpy(nxt_wasm_ctx.dirs[i], str.start, str.length);
+ }
+
+out_init:
err = nxt_wops->init(&nxt_wasm_ctx);
if (err) {
exit(EXIT_FAILURE);
diff --git a/src/wasm/nxt_wasm.h b/src/wasm/nxt_wasm.h
index 9e18f931..cb9dbdfe 100644
--- a/src/wasm/nxt_wasm.h
+++ b/src/wasm/nxt_wasm.h
@@ -110,6 +110,8 @@ struct nxt_wasm_ctx_s {
nxt_wasm_func_handler_t fh[NXT_WASM_FH_NR];
+ char **dirs;
+
nxt_unit_request_info_t *req;
uint8_t *baddr;