diff options
author | Casper Beyer <caspervonb@pm.me> | 2020-10-24 22:04:59 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-24 16:04:59 +0200 |
commit | 2a83b223857722ffe63aeaa35b44aec8659a910d (patch) | |
tree | 6b1a3d9981350f57082e8b0784dd2cc2fbd63c96 | |
parent | 35f184cdcca806bda72f65b73c774c53db132a3b (diff) |
fix(std/wasi): disallow path_open outside of pre-opened dirfd (#8078)
-rw-r--r-- | std/wasi/snapshot_preview1.ts | 36 | ||||
-rw-r--r-- | std/wasi/snapshot_preview1_test.ts | 14 | ||||
m--------- | std/wasi/testdata | 0 |
3 files changed, 44 insertions, 6 deletions
diff --git a/std/wasi/snapshot_preview1.ts b/std/wasi/snapshot_preview1.ts index dc2648efc..c8246b280 100644 --- a/std/wasi/snapshot_preview1.ts +++ b/std/wasi/snapshot_preview1.ts @@ -1,6 +1,6 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -import { resolve } from "../path/mod.ts"; +import { relative, resolve } from "../path/mod.ts"; const CLOCKID_REALTIME = 0; const CLOCKID_MONOTONIC = 1; @@ -83,7 +83,7 @@ const _ERRNO_STALE = 72; const ERRNO_TIMEDOUT = 73; const _ERRNO_TXTBSY = 74; const _ERRNO_XDEV = 75; -const _ERRNO_NOTCAPABLE = 76; +const ERRNO_NOTCAPABLE = 76; const RIGHTS_FD_DATASYNC = 0x0000000000000001n; const RIGHTS_FD_READ = 0x0000000000000002n; @@ -1201,9 +1201,35 @@ export default class Context { return ERRNO_INVAL; } - const text = new TextDecoder(); - const data = new Uint8Array(this.memory.buffer, pathOffset, pathLength); - const path = resolve(entry.path!, text.decode(data)); + const textDecoder = new TextDecoder(); + const pathData = new Uint8Array( + this.memory.buffer, + pathOffset, + pathLength, + ); + const resolvedPath = resolve(entry.path!, textDecoder.decode(pathData)); + + if (relative(entry.path, resolvedPath).startsWith("..")) { + return ERRNO_NOTCAPABLE; + } + + let path; + if ( + (dirflags & LOOKUPFLAGS_SYMLINK_FOLLOW) == LOOKUPFLAGS_SYMLINK_FOLLOW + ) { + try { + path = Deno.realPathSync(resolvedPath); + + console.log("RESOLVED REAL PATH: %s", path); + if (relative(entry.path, path).startsWith("..")) { + return ERRNO_NOTCAPABLE; + } + } catch (_err) { + path = resolvedPath; + } + } else { + path = resolvedPath; + } if ((oflags & OFLAGS_DIRECTORY) !== 0) { // XXX (caspervonb) this isn't ideal as we can't get a rid for the diff --git a/std/wasi/snapshot_preview1_test.ts b/std/wasi/snapshot_preview1_test.ts index 99f9145c7..a159a634c 100644 --- a/std/wasi/snapshot_preview1_test.ts +++ b/std/wasi/snapshot_preview1_test.ts @@ -35,6 +35,7 @@ const tests = [ "testdata/wasi_fd_write_file.wasm", "testdata/wasi_fd_write_stderr.wasm", "testdata/wasi_fd_write_stdout.wasm", + "testdata/wasi_path_open.wasm", "testdata/wasi_proc_exit.wasm", "testdata/wasi_random_get.wasm", "testdata/wasi_sched_yield.wasm", @@ -46,9 +47,13 @@ const ignore = [ // TODO(caspervonb) investigate why these tests are failing on windows and fix // them. +// The failing tests all involve symlinks in some way, my best guess so far is +// that there's something going wrong with copying the symlinks over to the +// temporary working directory, but only in some cases. if (Deno.build.os == "windows") { ignore.push("testdata/std_fs_metadata.wasm"); ignore.push("testdata/std_fs_read_dir.wasm"); + ignore.push("testdata/wasi_path_open.wasm"); } const rootdir = path.dirname(path.fromFileUrl(import.meta.url)); @@ -64,7 +69,14 @@ for (const pathname of tests) { ); const options = JSON.parse(prelude); - const workdir = await Deno.makeTempDir(); + // TODO(caspervonb) investigate more. + // On Windows creating a tempdir in the default directory breaks nearly + // all the tests, possibly due to symlinks pointing to the original file + // which crosses drive boundaries. + const workdir = await Deno.makeTempDir({ + dir: testdir, + }); + await copy( path.join(testdir, "fixtures"), path.join(workdir, "fixtures"), diff --git a/std/wasi/testdata b/std/wasi/testdata -Subproject ffbe85d2315ae0104534f38037903de38b6f2e6 +Subproject 324366afb925a3974c6135390c280aff9c4e0e9 |