Skip to content

Commit dc2cbab

Browse files
authored
Forbid fd_advise on directories (#240)
* Forbid fd_advise on directories This commit adds a check to `fd_advise`. If the fd is a directory, return `ebadf`. This brings uvwasi in line with Wasmtime's behavior. WASI folks have stated that fd_advise should not work on directories as this is a Linux-specific behavior.
1 parent ff7e84f commit dc2cbab

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

src/uvwasi.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
# include <dirent.h>
99
# include <time.h>
1010
#else
11+
# define _CRT_INTERNAL_NONSTDC_NAMES 1
12+
# include <sys/stat.h>
1113
# include <io.h>
1214
#endif /* _WIN32 */
1315

@@ -17,6 +19,10 @@
1719
# define UVWASI_FD_READDIR_SUPPORTED 1
1820
#endif
1921

22+
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
23+
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
24+
#endif
25+
2026
#include "uvwasi.h"
2127
#include "uvwasi_alloc.h"
2228
#include "uv.h"
@@ -627,9 +633,10 @@ uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi,
627633
uvwasi_advice_t advice) {
628634
struct uvwasi_fd_wrap_t* wrap;
629635
uvwasi_errno_t err;
636+
uv_fs_t req;
637+
int r;
630638
#ifdef POSIX_FADV_NORMAL
631639
int mapped_advice;
632-
int r;
633640
#endif /* POSIX_FADV_NORMAL */
634641

635642
UVWASI_DEBUG("uvwasi_fd_advise(uvwasi=%p, fd=%d, offset=%"PRIu64", "
@@ -682,14 +689,27 @@ uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi,
682689
if (err != UVWASI_ESUCCESS)
683690
return err;
684691

692+
r = uv_fs_fstat(NULL, &req, wrap->fd, NULL);
693+
if (r == -1) {
694+
err = uvwasi__translate_uv_error(r);
695+
goto exit;
696+
}
697+
698+
if (S_ISDIR(req.statbuf.st_mode)) {
699+
err = UVWASI_EBADF;
700+
goto exit;
701+
}
702+
685703
err = UVWASI_ESUCCESS;
686704

687705
#ifdef POSIX_FADV_NORMAL
688706
r = posix_fadvise(wrap->fd, offset, len, mapped_advice);
689707
if (r != 0)
690708
err = uvwasi__translate_uv_error(uv_translate_sys_error(r));
691709
#endif /* POSIX_FADV_NORMAL */
710+
exit:
692711
uv_mutex_unlock(&wrap->mutex);
712+
uv_fs_req_cleanup(&req);
693713
return err;
694714
}
695715

test/test-fd-advise-dir.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
#include "uv.h"
5+
#include "uvwasi.h"
6+
#include "test-common.h"
7+
8+
#define TEST_TMP_DIR "./out/tmp"
9+
#define TEST_PATH_ADVISE TEST_TMP_DIR "/test_fd_advise_dir"
10+
11+
int main(void) {
12+
#if !defined(_WIN32) && !defined(__ANDROID__)
13+
uvwasi_t uvwasi;
14+
uvwasi_options_t init_options;
15+
uv_fs_t req;
16+
uvwasi_errno_t err;
17+
int r;
18+
19+
setup_test_environment();
20+
21+
r = uv_fs_mkdir(NULL, &req, TEST_TMP_DIR, 0777, NULL);
22+
uv_fs_req_cleanup(&req);
23+
assert(r == 0 || r == UV_EEXIST);
24+
25+
r = uv_fs_mkdir(NULL, &req, TEST_PATH_ADVISE, 0777, NULL);
26+
uv_fs_req_cleanup(&req);
27+
assert(r == 0 || r == UV_EEXIST);
28+
29+
uvwasi_options_init(&init_options);
30+
init_options.preopenc = 1;
31+
init_options.preopens = calloc(1, sizeof(uvwasi_preopen_t));
32+
init_options.preopens[0].mapped_path = "/var";
33+
init_options.preopens[0].real_path = TEST_PATH_ADVISE;
34+
35+
err = uvwasi_init(&uvwasi, &init_options);
36+
assert(err == 0);
37+
38+
err = uvwasi_fd_advise(&uvwasi, 3, 10, 20, UVWASI_ADVICE_DONTNEED);
39+
assert(err == UVWASI_EBADF);
40+
41+
uvwasi_destroy(&uvwasi);
42+
free(init_options.preopens);
43+
#endif /* !defined(_WIN32) && !defined(__ANDROID__) */
44+
return 0;
45+
}

0 commit comments

Comments
 (0)