diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 3038e3d44b..c9a8ea0ae6 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -417,6 +417,24 @@ fd_prestats_get_entry(struct fd_prestats *pt, __wasi_fd_t fd, return 0; } +// Remove a preopened resource record from the preopened resource table by +// number +static __wasi_errno_t +fd_prestats_remove_entry(struct fd_prestats *pt, __wasi_fd_t fd) +{ + // Test for file descriptor existence. + if (fd >= pt->size) + return __WASI_EBADF; + struct fd_prestat *prestat = &pt->prestats[fd]; + + if (prestat->dir != NULL) { + wasm_runtime_free((void *)prestat->dir); + prestat->dir = NULL; + } + + return 0; +} + struct fd_object { struct refcount refcount; __wasi_filetype_t type; @@ -825,12 +843,14 @@ wasmtime_ssp_fd_prestat_dir_name( rwlock_unlock(&prestats->lock); return error; } - if (path_len != strlen(prestat->dir)) { + + const int prestat_dir_len = strlen(prestat->dir); + if (path_len < prestat_dir_len) { rwlock_unlock(&prestats->lock); - return EINVAL; + return __WASI_ENAMETOOLONG; } - bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)path_len); + bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)prestat_dir_len); rwlock_unlock(&prestats->lock); @@ -844,25 +864,15 @@ wasmtime_ssp_fd_close( #endif __wasi_fd_t fd) { - // Don't allow closing a pre-opened resource. - // TODO: Eventually, we do want to permit this, once libpreopen in - // userspace is capable of removing entries from its tables as well. - { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); - rwlock_unlock(&prestats->lock); - if (error == 0) { - return __WASI_ENOTSUP; - } - } - // Validate the file descriptor. struct fd_table *ft = curfds; rwlock_wrlock(&ft->lock); + rwlock_wrlock(&prestats->lock); + struct fd_entry *fe; __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); if (error != 0) { + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); return error; } @@ -870,8 +880,19 @@ wasmtime_ssp_fd_close( // Remove it from the file descriptor table. struct fd_object *fo; fd_table_detach(ft, fd, &fo); + + // Remove it from the preopened resource table if it exists + error = fd_prestats_remove_entry(prestats, fd); + + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); + fd_object_release(fo); + + if (error != __WASI_EBADF && error != 0) { + return error; + } + return 0; } @@ -1093,33 +1114,21 @@ wasmtime_ssp_fd_renumber( #endif __wasi_fd_t from, __wasi_fd_t to) { - // Don't allow renumbering over a pre-opened resource. - // TODO: Eventually, we do want to permit this, once libpreopen in - // userspace is capable of removing entries from its tables as well. - { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, to, &prestat); - if (error != 0) { - error = fd_prestats_get_entry(prestats, from, &prestat); - } - rwlock_unlock(&prestats->lock); - if (error == 0) { - return __WASI_ENOTSUP; - } - } - struct fd_table *ft = curfds; rwlock_wrlock(&ft->lock); + rwlock_wrlock(&prestats->lock); + struct fd_entry *fe_from; __wasi_errno_t error = fd_table_get_entry(ft, from, 0, 0, &fe_from); if (error != 0) { + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); return error; } struct fd_entry *fe_to; error = fd_table_get_entry(ft, to, 0, 0, &fe_to); if (error != 0) { + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); return error; } @@ -1136,7 +1145,45 @@ wasmtime_ssp_fd_renumber( fd_object_release(fo); --ft->used; + // Handle renumbering of any preopened resources + struct fd_prestat *prestat_from; + __wasi_errno_t prestat_from_error = + fd_prestats_get_entry(prestats, from, &prestat_from); + + struct fd_prestat *prestat_to; + __wasi_errno_t prestat_to_error = + fd_prestats_get_entry(prestats, to, &prestat_to); + + // Renumbering over two preopened resources. + if (prestat_from_error == 0 && prestat_to_error == 0) { + error = fd_prestats_remove_entry(prestats, to); + + if (error == 0) { + prestat_to->dir = bh_strdup(prestat_from->dir); + + if (prestat_to->dir != NULL) { + error = fd_prestats_remove_entry(prestats, from); + } + } + } + // Renumbering from a non-preopened fd to a preopened fd. In this case, we + // can't a keep the destination fd entry in the preopened table so remove + // it entirely. + else if (prestat_from_error != 0 && prestat_to_error == 0) { + error = fd_prestats_remove_entry(prestats, to); + } + // Renumbering from a preopened fd to a non-preopened fd + else if (prestat_from_error == 0 && prestat_to_error != 0) { + error = fd_prestats_remove_entry(prestats, from); + } + + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); + + if (error != 0) { + return error; + } + return 0; } @@ -1941,31 +1988,20 @@ wasmtime_ssp_path_open( needed_base |= __WASI_RIGHT_PATH_FILESTAT_SET_SIZE; } + // It's not clear whether we want to support these flags in the standard + // yet: https://github.com/WebAssembly/wasi-filesystem/issues/98 so disable + // them in the meanwhile. + if (((fs_flags & __WASI_FDFLAG_DSYNC) != 0) + || ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) + || ((fs_flags & __WASI_FDFLAG_SYNC) != 0)) { + return __WASI_ENOTSUP; + } + // Convert file descriptor flags. if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) noflags |= O_APPEND; - if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) { -#ifdef O_DSYNC - noflags |= O_DSYNC; -#else - noflags |= O_SYNC; -#endif - needed_inheriting |= __WASI_RIGHT_FD_DATASYNC; - } if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) noflags |= O_NONBLOCK; - if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) { -#ifdef O_RSYNC - noflags |= O_RSYNC; -#else - noflags |= O_SYNC; -#endif - needed_inheriting |= __WASI_RIGHT_FD_SYNC; - } - if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) { - noflags |= O_SYNC; - needed_inheriting |= __WASI_RIGHT_FD_SYNC; - } if (write && (noflags & (O_APPEND | O_TRUNC)) == 0) needed_inheriting |= __WASI_RIGHT_FD_SEEK; @@ -2021,20 +2057,6 @@ wasmtime_ssp_path_open( return error; } - { - struct stat sb; - - if (fstat(nfd, &sb) < 0) { - close(nfd); - return convert_errno(errno); - } - - if (S_ISDIR(sb.st_mode)) - rights_base |= (__wasi_rights_t)RIGHTS_DIRECTORY_BASE; - else if (S_ISREG(sb.st_mode)) - rights_base |= (__wasi_rights_t)RIGHTS_REGULAR_FILE_BASE; - } - return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base, rights_inheriting & max_inheriting, fd); } @@ -3677,7 +3699,8 @@ argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf, void argv_environ_destroy(struct argv_environ_values *argv_environ) -{} +{ +} void fd_table_destroy(struct fd_table *ft) diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 1448e3e1e3..e5772fcd71 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -55,7 +55,7 @@ PLATFORM=$(uname -s | tr A-Z a-z) PARALLELISM=0 ENABLE_QEMU=0 QEMU_FIRMWARE="" -WASI_TESTSUITE_COMMIT="aca78d919355ae00af141e6741a439039615b257" +WASI_TESTSUITE_COMMIT="023e1b0dd49388badbfe9553ab2d20a931ba662d" while getopts ":s:cabgvt:m:MCpSXxwPGQF:" opt do diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index 454fbb142f..a932a615f6 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -18,6 +18,7 @@ readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/b readonly IWASM_CMD_STRESS="${IWASM_CMD} --max-threads=8" readonly WAMRC_CMD="${WORK_DIR}/../../../../wamr-compiler/build/wamrc" readonly C_TESTS="tests/c/testsuite/" +readonly RUST_TESTS="tests/rust/testsuite/" readonly ASSEMBLYSCRIPT_TESTS="tests/assemblyscript/testsuite/" readonly THREAD_PROPOSAL_TESTS="tests/proposals/wasi-threads/" readonly THREAD_INTERNAL_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/test/" @@ -83,6 +84,7 @@ if [[ $MODE != "aot" ]];then -r adapters/wasm-micro-runtime.py \ -t \ ${C_TESTS} \ + ${RUST_TESTS} \ ${ASSEMBLYSCRIPT_TESTS} \ ${THREAD_PROPOSAL_TESTS} \ ${THREAD_INTERNAL_TESTS} \