Skip to content

Commit 98da5ad

Browse files
authored
Resolve old_path in uvwasi_path_symlink() (#303)
- add test-symlink-outbox
1 parent 76e9211 commit 98da5ad

File tree

2 files changed

+137
-18
lines changed

2 files changed

+137
-18
lines changed

src/uvwasi.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
807807
uv_mutex_unlock(&wrap->mutex);
808808
if (err != UVWASI_ESUCCESS) {
809809
goto exit;
810-
}
810+
}
811811
}
812812

813813
if (r != 0) {
@@ -2370,6 +2370,7 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi,
23702370
const char* new_path,
23712371
uvwasi_size_t new_path_len) {
23722372
char* truncated_old_path;
2373+
char* resolved_old_path;
23732374
char* resolved_new_path;
23742375
struct uvwasi_fd_wrap_t* wrap;
23752376
uvwasi_errno_t err;
@@ -2396,46 +2397,61 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi,
23962397
if (err != UVWASI_ESUCCESS)
23972398
return err;
23982399

2400+
resolved_old_path = NULL;
2401+
resolved_new_path = NULL;
2402+
truncated_old_path = NULL;
2403+
23992404
truncated_old_path = uvwasi__malloc(uvwasi, old_path_len + 1);
24002405
if (truncated_old_path == NULL) {
2401-
uv_mutex_unlock(&wrap->mutex);
2402-
return UVWASI_ENOMEM;
2406+
err = UVWASI_ENOMEM;
2407+
goto exit;
24032408
}
24042409

24052410
memcpy(truncated_old_path, old_path, old_path_len);
24062411
truncated_old_path[old_path_len] = '\0';
24072412

24082413
if (old_path_len > 0 && old_path[0] == '/') {
2409-
uv_mutex_unlock(&wrap->mutex);
2410-
uvwasi__free(uvwasi, truncated_old_path);
2411-
return UVWASI_EPERM;
2414+
err = UVWASI_EPERM;
2415+
goto exit;
24122416
}
24132417

2418+
err = uvwasi__resolve_path(uvwasi,
2419+
wrap,
2420+
old_path,
2421+
old_path_len,
2422+
&resolved_old_path,
2423+
0);
2424+
if (err != UVWASI_ESUCCESS)
2425+
goto exit;
2426+
24142427
err = uvwasi__resolve_path(uvwasi,
24152428
wrap,
24162429
new_path,
24172430
new_path_len,
24182431
&resolved_new_path,
24192432
0);
2420-
if (err != UVWASI_ESUCCESS) {
2421-
uv_mutex_unlock(&wrap->mutex);
2422-
uvwasi__free(uvwasi, truncated_old_path);
2423-
return err;
2424-
}
2433+
if (err != UVWASI_ESUCCESS)
2434+
goto exit;
2435+
24252436

24262437
/* Windows support may require setting the flags option. */
24272438
r = uv_fs_symlink(NULL, &req, truncated_old_path, resolved_new_path, 0, NULL);
2439+
uv_fs_req_cleanup(&req);
2440+
if (r != 0) {
2441+
err = uvwasi__translate_uv_error(r);
2442+
goto exit;
2443+
}
2444+
2445+
err = UVWASI_ESUCCESS;
2446+
exit:
24282447
uv_mutex_unlock(&wrap->mutex);
2429-
uvwasi__free(uvwasi, truncated_old_path);
2448+
uvwasi__free(uvwasi, resolved_old_path);
24302449
uvwasi__free(uvwasi, resolved_new_path);
2431-
uv_fs_req_cleanup(&req);
2432-
if (r != 0)
2433-
return uvwasi__translate_uv_error(r);
2450+
uvwasi__free(uvwasi, truncated_old_path);
24342451

2435-
return UVWASI_ESUCCESS;
2452+
return err;
24362453
}
24372454

2438-
24392455
uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi,
24402456
uvwasi_fd_t fd,
24412457
const char* path,
@@ -2808,7 +2824,7 @@ uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi,
28082824

28092825
uv_mutex_unlock(&wrap->mutex);
28102826

2811-
if (shutdown_data.status != 0)
2827+
if (shutdown_data.status != 0)
28122828
return uvwasi__translate_uv_error(shutdown_data.status);
28132829

28142830
return UVWASI_ESUCCESS;

test/test-symlink-outbox.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include "uvwasi.h"
5+
#include "uv.h"
6+
#include "test-common.h"
7+
8+
#define TEST_TMP_DIR "./out/tmp"
9+
#define SECRET_FILE "secret"
10+
#define SECRET_CONTENT "I am a password"
11+
#define TEST_DIR "tdir"
12+
#define BUFFER_SIZE 1024
13+
14+
void setup() {
15+
uv_fs_t req;
16+
int r;
17+
18+
// write SECRET_CONTENT to SECRET_FILE
19+
char path[128];
20+
snprintf(path, sizeof(path), "%s/%s", TEST_TMP_DIR, SECRET_FILE);
21+
r = uv_fs_open(NULL, &req, path, O_WRONLY | O_CREAT, 0644, NULL);
22+
uv_fs_req_cleanup(&req);
23+
assert(r >= 0 || r == UV_EEXIST);
24+
25+
int secret_fd = r;
26+
uv_buf_t buf = uv_buf_init((char*)SECRET_CONTENT, strlen(SECRET_CONTENT));
27+
r = uv_fs_write(NULL, &req, secret_fd, &buf, 1, -1, NULL);
28+
uv_fs_req_cleanup(&req);
29+
assert(r == (int)strlen(SECRET_CONTENT));
30+
31+
r = uv_fs_close(NULL, &req, secret_fd, NULL);
32+
uv_fs_req_cleanup(&req);
33+
assert(r == 0);
34+
35+
snprintf(path, sizeof(path), "%s/%s", TEST_TMP_DIR, TEST_DIR);
36+
r = uv_fs_mkdir(NULL, &req, path, 0777, NULL);
37+
uv_fs_req_cleanup(&req);
38+
assert(r == 0 || r == UV_EEXIST);
39+
}
40+
41+
void teardown() {
42+
uv_fs_t req;
43+
int r;
44+
45+
char path[128];
46+
snprintf(path, sizeof(path), "%s/%s", TEST_TMP_DIR, SECRET_FILE);
47+
r = uv_fs_unlink(NULL, &req, path, NULL);
48+
uv_fs_req_cleanup(&req);
49+
assert(r == 0 || r == UV_ENOENT);
50+
51+
snprintf(path, sizeof(path), "%s/%s", TEST_TMP_DIR, TEST_DIR);
52+
r = uv_fs_rmdir(NULL, &req, path, NULL);
53+
uv_fs_req_cleanup(&req);
54+
assert(r == 0 || r == UV_ENOENT);
55+
}
56+
57+
int main(void) {
58+
const char* target_path = "../secret";
59+
const char* linkname = "./invalid_symlink.txt";
60+
char preopen_path[128];
61+
uvwasi_t uvwasi;
62+
uvwasi_options_t init_options;
63+
uvwasi_errno_t err;
64+
uv_fs_t req;
65+
int r;
66+
67+
setup_test_environment();
68+
69+
r = uv_fs_mkdir(NULL, &req, TEST_TMP_DIR, 0777, NULL);
70+
uv_fs_req_cleanup(&req);
71+
assert(r == 0 || r == UV_EEXIST);
72+
73+
setup();
74+
75+
snprintf(preopen_path, sizeof(preopen_path), "%s/%s", TEST_TMP_DIR, TEST_DIR);
76+
77+
uvwasi_options_init(&init_options);
78+
init_options.preopenc = 1;
79+
init_options.preopens = calloc(1, sizeof(uvwasi_preopen_t));
80+
init_options.preopens[0].mapped_path = preopen_path;
81+
init_options.preopens[0].real_path = preopen_path;
82+
83+
err = uvwasi_init(&uvwasi, &init_options);
84+
assert(err == 0);
85+
86+
// Attempt to create a symlink with a target path that resolves to the parent directory
87+
err = uvwasi_path_symlink(&uvwasi,
88+
target_path,
89+
strlen(target_path),
90+
3,
91+
linkname,
92+
strlen(linkname));
93+
94+
// Assert that the operation fails
95+
// Expecting an error due to invalid target path
96+
assert(err == UVWASI_ENOTCAPABLE);
97+
98+
free(init_options.preopens);
99+
uvwasi_destroy(&uvwasi);
100+
101+
teardown();
102+
return 0;
103+
}

0 commit comments

Comments
 (0)