core/iwasm: Support mapped file system access on non-libuv WASI (#2628)

This patch enables mapping host directories to guest directories by parsing
the `map_dir_list` argument in API `wasm_runtime_init_wasi` for libc-wasi. It
follows the format `<guest-path>::<host-path>`.

It also adds argument `--map-dir=<guest::host>` argument for `iwasm`
common line tool, and allows to add multiple mappings:
```bash
iwasm --map-dir=<guest-path1::host-path1> --map-dir=<guest-path2::host-path2> ...
```
This commit is contained in:
Alfred E. Neumayer 2023-10-27 06:48:10 +02:00 committed by GitHub
parent 8038b9c524
commit 9b8fe049b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 4 deletions

View File

@ -3012,8 +3012,82 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
goto fail; goto fail;
} }
fd_table_insert_existing(curfds, wasm_fd, raw_fd); if (!fd_table_insert_existing(curfds, wasm_fd, raw_fd)
fd_prestats_insert(prestats, dir_list[i], wasm_fd); || !fd_prestats_insert(prestats, dir_list[i], wasm_fd)) {
if (error_buf)
snprintf(
error_buf, error_buf_size,
"error while pre-opening directory %s: insertion failed\n",
dir_list[i]);
goto fail;
}
}
for (i = 0; i < map_dir_count; i++, wasm_fd++) {
char mapping_copy_buf[256];
char *mapping_copy = mapping_copy_buf;
char *map_mapped = NULL, *map_host = NULL;
const unsigned long max_len = strlen(map_dir_list[i]) * 2 + 3;
/* Allocation limit for runtime environments with reduced stack size */
if (max_len > 256) {
if (!(mapping_copy = wasm_runtime_malloc(max_len))) {
snprintf(error_buf, error_buf_size,
"error while allocating for directory mapping\n");
goto fail;
}
}
strncpy(mapping_copy, map_dir_list[i], strlen(map_dir_list[i]) + 1);
map_mapped = strtok(mapping_copy, "::");
map_host = strtok(NULL, "::");
if (!map_mapped || !map_host) {
if (error_buf)
snprintf(error_buf, error_buf_size,
"error while pre-opening mapped directory: "
"invalid map\n");
if (mapping_copy != mapping_copy_buf)
wasm_runtime_free(mapping_copy);
goto fail;
}
path = realpath(map_host, resolved_path);
if (!path) {
if (error_buf)
snprintf(error_buf, error_buf_size,
"error while pre-opening mapped directory %s: %d\n",
map_host, errno);
if (mapping_copy != mapping_copy_buf)
wasm_runtime_free(mapping_copy);
goto fail;
}
raw_fd = open(path, O_RDONLY | O_DIRECTORY, 0);
if (raw_fd == -1) {
if (error_buf)
snprintf(error_buf, error_buf_size,
"error while pre-opening mapped directory %s: %d\n",
map_host, errno);
if (mapping_copy != mapping_copy_buf)
wasm_runtime_free(mapping_copy);
goto fail;
}
if (!fd_table_insert_existing(curfds, wasm_fd, raw_fd)
|| !fd_prestats_insert(prestats, map_mapped, wasm_fd)) {
if (error_buf)
snprintf(error_buf, error_buf_size,
"error while pre-opening mapped directory %s: "
"insertion failed\n",
dir_list[i]);
if (mapping_copy != mapping_copy_buf)
wasm_runtime_free(mapping_copy);
goto fail;
}
if (mapping_copy != mapping_copy_buf)
wasm_runtime_free(mapping_copy);
} }
/* addr_pool(textual) -> apool */ /* addr_pool(textual) -> apool */

View File

@ -423,6 +423,7 @@ wasm_runtime_get_module_hash(wasm_module_t module);
* @param dir_list The list of directories to preopen. (real path) * @param dir_list The list of directories to preopen. (real path)
* @param dir_count The number of elements in dir_list. * @param dir_count The number of elements in dir_list.
* @param map_dir_list The list of directories to preopen. (mapped path) * @param map_dir_list The list of directories to preopen. (mapped path)
* Format for each map entry: <guest-path>::<host-path>
* @param map_dir_count The number of elements in map_dir_list. * @param map_dir_count The number of elements in map_dir_list.
* If map_dir_count is smaller than dir_count, * If map_dir_count is smaller than dir_count,
* mapped path is assumed to be same as the * mapped path is assumed to be same as the

View File

@ -75,6 +75,9 @@ print_help()
printf(" --dir=<dir> Grant wasi access to the given host directories\n"); printf(" --dir=<dir> Grant wasi access to the given host directories\n");
printf(" to the program, for example:\n"); printf(" to the program, for example:\n");
printf(" --dir=<dir1> --dir=<dir2>\n"); printf(" --dir=<dir1> --dir=<dir2>\n");
printf(" --map-dir=<guest::host> Grant wasi access to the given host directories\n");
printf(" to the program at a specific guest path, for example:\n");
printf(" --map-dir=<guest-path1::host-path1> --map-dir=<guest-path2::host-path2>\n");
printf(" --addr-pool=<addrs> Grant wasi access to the given network addresses in\n"); printf(" --addr-pool=<addrs> Grant wasi access to the given network addresses in\n");
printf(" CIRD notation to the program, seperated with ',',\n"); printf(" CIRD notation to the program, seperated with ',',\n");
printf(" for example:\n"); printf(" for example:\n");
@ -573,6 +576,8 @@ main(int argc, char *argv[])
#if WASM_ENABLE_LIBC_WASI != 0 #if WASM_ENABLE_LIBC_WASI != 0
const char *dir_list[8] = { NULL }; const char *dir_list[8] = { NULL };
uint32 dir_list_size = 0; uint32 dir_list_size = 0;
const char *map_dir_list[8] = { NULL };
uint32 map_dir_list_size = 0;
const char *env_list[8] = { NULL }; const char *env_list[8] = { NULL };
uint32 env_list_size = 0; uint32 env_list_size = 0;
const char *addr_pool[8] = { NULL }; const char *addr_pool[8] = { NULL };
@ -711,6 +716,16 @@ main(int argc, char *argv[])
} }
dir_list[dir_list_size++] = argv[0] + 6; dir_list[dir_list_size++] = argv[0] + 6;
} }
else if (!strncmp(argv[0], "--map-dir=", 10)) {
if (argv[0][10] == '\0')
return print_help();
if (map_dir_list_size >= sizeof(map_dir_list) / sizeof(char *)) {
printf("Only allow max map dir number %d\n",
(int)(sizeof(map_dir_list) / sizeof(char *)));
return 1;
}
map_dir_list[map_dir_list_size++] = argv[0] + 10;
}
else if (!strncmp(argv[0], "--env=", 6)) { else if (!strncmp(argv[0], "--env=", 6)) {
char *tmp_env; char *tmp_env;
@ -920,8 +935,9 @@ main(int argc, char *argv[])
} }
#if WASM_ENABLE_LIBC_WASI != 0 #if WASM_ENABLE_LIBC_WASI != 0
wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size,
env_list, env_list_size, argv, argc); map_dir_list, map_dir_list_size, env_list,
env_list_size, argv, argc);
wasm_runtime_set_wasi_addr_pool(wasm_module, addr_pool, addr_pool_size); wasm_runtime_set_wasi_addr_pool(wasm_module, addr_pool, addr_pool_size);
wasm_runtime_set_wasi_ns_lookup_pool(wasm_module, ns_lookup_pool, wasm_runtime_set_wasi_ns_lookup_pool(wasm_module, ns_lookup_pool,