From 1a6fd38f2f7b016714ec313ce234fd5356aa956a Mon Sep 17 00:00:00 2001 From: David Sherret Date: Tue, 27 Aug 2024 22:03:09 -0400 Subject: fix(permissions): disallow launching subprocess with LD_PRELOAD env var without full run permissions (#25221) Ref https://github.com/denoland/deno/pull/25215 Closes https://github.com/denoland/deno/issues/11964 --- runtime/ops/process.rs | 20 +++++++++++++++++--- tests/specs/run/ld_preload/__test__.jsonc | 14 ++++++++++++++ tests/specs/run/ld_preload/env_arg.out | 4 ++++ tests/specs/run/ld_preload/env_arg.ts | 5 +++++ tests/specs/run/ld_preload/set_with_allow_env.out | 4 ++++ tests/specs/run/ld_preload/set_with_allow_env.ts | 3 +++ 6 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 tests/specs/run/ld_preload/__test__.jsonc create mode 100644 tests/specs/run/ld_preload/env_arg.out create mode 100644 tests/specs/run/ld_preload/env_arg.ts create mode 100644 tests/specs/run/ld_preload/set_with_allow_env.out create mode 100644 tests/specs/run/ld_preload/set_with_allow_env.ts diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs index 9d166a801..564092454 100644 --- a/runtime/ops/process.rs +++ b/runtime/ops/process.rs @@ -229,9 +229,23 @@ fn create_command( mut args: SpawnArgs, api_name: &str, ) -> Result { - state - .borrow_mut::() - .check_run(&args.cmd, api_name)?; + { + let permissions = state.borrow_mut::(); + permissions.check_run(&args.cmd, api_name)?; + // error the same on all platforms + if permissions.check_run_all(api_name).is_err() + && (args.env.iter().any(|(k, _)| k.trim() == "LD_PRELOAD") + || !args.clear_env + && std::env::vars().any(|(k, _)| k.trim() == "LD_PRELOAD")) + { + // we don't allow users to launch subprocesses with the LD_PRELOAD + // env var set because this allows executing any code + return Err(deno_core::error::custom_error( + "PermissionDenied", + "Requires --allow-all permissions to spawn subprocess with LD_PRELOAD environment variable." + )); + } + } let mut command = std::process::Command::new(args.cmd); diff --git a/tests/specs/run/ld_preload/__test__.jsonc b/tests/specs/run/ld_preload/__test__.jsonc new file mode 100644 index 000000000..f3a9b26bc --- /dev/null +++ b/tests/specs/run/ld_preload/__test__.jsonc @@ -0,0 +1,14 @@ +{ + "tests": { + "env_arg": { + "args": "run --allow-run=echo env_arg.ts", + "output": "env_arg.out", + "exitCode": 1 + }, + "set_with_allow_env": { + "args": "run --allow-run=echo --allow-env set_with_allow_env.ts", + "output": "set_with_allow_env.out", + "exitCode": 1 + } + } +} diff --git a/tests/specs/run/ld_preload/env_arg.out b/tests/specs/run/ld_preload/env_arg.out new file mode 100644 index 000000000..fbf37014a --- /dev/null +++ b/tests/specs/run/ld_preload/env_arg.out @@ -0,0 +1,4 @@ +error: Uncaught (in promise) PermissionDenied: Requires --allow-all permissions to spawn subprocess with LD_PRELOAD environment variable. +}).spawn(); + ^ + at [WILDCARD] diff --git a/tests/specs/run/ld_preload/env_arg.ts b/tests/specs/run/ld_preload/env_arg.ts new file mode 100644 index 000000000..0b236619e --- /dev/null +++ b/tests/specs/run/ld_preload/env_arg.ts @@ -0,0 +1,5 @@ +const output = new Deno.Command("echo", { + env: { + "LD_PRELOAD": "./libpreload.so", + }, +}).spawn(); diff --git a/tests/specs/run/ld_preload/set_with_allow_env.out b/tests/specs/run/ld_preload/set_with_allow_env.out new file mode 100644 index 000000000..2e92763dd --- /dev/null +++ b/tests/specs/run/ld_preload/set_with_allow_env.out @@ -0,0 +1,4 @@ +error: Uncaught (in promise) PermissionDenied: Requires --allow-all permissions to spawn subprocess with LD_PRELOAD environment variable. +const output = new Deno.Command("echo").spawn(); + ^ + at [WILDCARD] diff --git a/tests/specs/run/ld_preload/set_with_allow_env.ts b/tests/specs/run/ld_preload/set_with_allow_env.ts new file mode 100644 index 000000000..9530f4478 --- /dev/null +++ b/tests/specs/run/ld_preload/set_with_allow_env.ts @@ -0,0 +1,3 @@ +Deno.env.set("LD_PRELOAD", "./libpreload.so"); + +const output = new Deno.Command("echo").spawn(); -- cgit v1.2.3