summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/permissions/lib.rs39
-rw-r--r--tests/specs/permission/proc_self_fd/__test__.jsonc5
-rw-r--r--tests/specs/permission/proc_self_fd/main.js18
-rw-r--r--tests/specs/permission/proc_self_fd/reader.ts1
4 files changed, 63 insertions, 0 deletions
diff --git a/runtime/permissions/lib.rs b/runtime/permissions/lib.rs
index 70d1abae7..06db9958c 100644
--- a/runtime/permissions/lib.rs
+++ b/runtime/permissions/lib.rs
@@ -1680,7 +1680,46 @@ impl PermissionsContainer {
return Ok(());
}
+ /// We'll allow opening /proc/self/fd/{n} without additional permissions under the following conditions:
+ ///
+ /// 1. n > 2. This allows for opening bash-style redirections, but not stdio
+ /// 2. the fd referred to by n is a pipe
+ #[cfg(unix)]
+ fn is_fd_file_is_pipe(path: &Path) -> bool {
+ if let Some(fd) = path.file_name() {
+ if let Ok(s) = std::str::from_utf8(fd.as_encoded_bytes()) {
+ if let Ok(n) = s.parse::<i32>() {
+ if n > 2 {
+ // SAFETY: This is proper use of the stat syscall
+ unsafe {
+ let mut stat = std::mem::zeroed::<libc::stat>();
+ if libc::fstat(n, &mut stat as _) == 0
+ && ((stat.st_mode & libc::S_IFMT) & libc::S_IFIFO) != 0
+ {
+ return true;
+ }
+ };
+ }
+ }
+ }
+ }
+ false
+ }
+
+ // On unixy systems, we allow opening /dev/fd/XXX for valid FDs that
+ // are pipes.
+ #[cfg(unix)]
+ if path.starts_with("/dev/fd") && is_fd_file_is_pipe(path) {
+ return Ok(());
+ }
+
if cfg!(target_os = "linux") {
+ // On Linux, we also allow opening /proc/self/fd/XXX for valid FDs that
+ // are pipes.
+ #[cfg(unix)]
+ if path.starts_with("/proc/self/fd") && is_fd_file_is_pipe(path) {
+ return Ok(());
+ }
if path.starts_with("/dev")
|| path.starts_with("/proc")
|| path.starts_with("/sys")
diff --git a/tests/specs/permission/proc_self_fd/__test__.jsonc b/tests/specs/permission/proc_self_fd/__test__.jsonc
new file mode 100644
index 000000000..8d4d1ed43
--- /dev/null
+++ b/tests/specs/permission/proc_self_fd/__test__.jsonc
@@ -0,0 +1,5 @@
+{
+ "args": "run -A main.js",
+ "output": "hi\n\n0\n",
+ "exitCode": 123
+}
diff --git a/tests/specs/permission/proc_self_fd/main.js b/tests/specs/permission/proc_self_fd/main.js
new file mode 100644
index 000000000..86d8334cb
--- /dev/null
+++ b/tests/specs/permission/proc_self_fd/main.js
@@ -0,0 +1,18 @@
+// This test is Linux/Darwin only
+if (Deno.build.os !== "linux" && Deno.build.os !== "darwin") {
+ console.log("hi\n\n0");
+ Deno.exit(123);
+}
+
+const cmd = new Deno.Command("/usr/bin/env", {
+ args: [
+ "bash",
+ "-c",
+ [Deno.execPath(), "run", "--allow-read", "reader.ts", '<(echo "hi")'].join(
+ " ",
+ ),
+ ],
+}).spawn();
+
+console.log((await cmd.status).code);
+Deno.exit(123);
diff --git a/tests/specs/permission/proc_self_fd/reader.ts b/tests/specs/permission/proc_self_fd/reader.ts
new file mode 100644
index 000000000..4b3587fa2
--- /dev/null
+++ b/tests/specs/permission/proc_self_fd/reader.ts
@@ -0,0 +1 @@
+console.log(Deno.readTextFileSync(Deno.args[0]));