Skip to content

Commit

Permalink
fix(runtime): Allow opening /dev/fd/XXX for unix (#23743)
Browse files Browse the repository at this point in the history
`deno run script.ts <(some command)` is a valid use case -- let's allow
this to work without `--allow-all`.

Fixes #23703
  • Loading branch information
mmastrac authored and dsherret committed May 10, 2024
1 parent 15affcb commit 95ae9ea
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 0 deletions.
39 changes: 39 additions & 0 deletions runtime/permissions/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
5 changes: 5 additions & 0 deletions tests/specs/permission/proc_self_fd/__test__.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"args": "run -A main.js",
"output": "hi\n\n0\n",
"exitCode": 123
}
18 changes: 18 additions & 0 deletions tests/specs/permission/proc_self_fd/main.js
Original file line number Diff line number Diff line change
@@ -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);
1 change: 1 addition & 0 deletions tests/specs/permission/proc_self_fd/reader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log(Deno.readTextFileSync(Deno.args[0]));

0 comments on commit 95ae9ea

Please sign in to comment.