Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: permission stack traces in ops #26758

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 12 additions & 41 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ repository = "https://github.com/denoland/deno"

[workspace.dependencies]
deno_ast = { version = "=0.43.3", features = ["transpiling"] }
deno_core = { version = "0.318.0" }
deno_core = { version = "0.319.0" }

deno_bench_util = { version = "0.170.0", path = "./bench_util" }
deno_lockfile = "=0.23.1"
Expand Down
2 changes: 2 additions & 0 deletions cli/file_fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,12 +656,14 @@ impl FileFetcher {
permissions.check_specifier(
specifier,
deno_runtime::deno_permissions::CheckSpecifierKind::Static,
None,
)?;
}
FetchPermissionsOptionRef::DynamicContainer(permissions) => {
permissions.check_specifier(
specifier,
deno_runtime::deno_permissions::CheckSpecifierKind::Dynamic,
None,
)?;
}
}
Expand Down
5 changes: 4 additions & 1 deletion cli/module_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1065,14 +1065,17 @@ impl<TGraphContainer: ModuleGraphContainer> NodeRequireLoader
&self,
permissions: &mut dyn deno_runtime::deno_node::NodePermissions,
path: &'a Path,
stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<std::borrow::Cow<'a, Path>, AnyError> {
if let Ok(url) = deno_path_util::url_from_file_path(path) {
// allow reading if it's in the module graph
if self.graph_container.graph().get(&url).is_some() {
return Ok(std::borrow::Cow::Borrowed(path));
}
}
self.npm_resolver.ensure_read_permission(permissions, path)
self
.npm_resolver
.ensure_read_permission(permissions, path, stack)
}

fn load_text_file_lossy(&self, path: &Path) -> Result<String, AnyError> {
Expand Down
3 changes: 2 additions & 1 deletion cli/npm/byonm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,13 @@ impl CliNpmResolver for CliByonmNpmResolver {
&self,
permissions: &mut dyn NodePermissions,
path: &'a Path,
stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<Cow<'a, Path>, AnyError> {
if !path
.components()
.any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules")
{
permissions.check_read_path(path).map_err(Into::into)
permissions.check_read_path(path, stack).map_err(Into::into)
} else {
Ok(Cow::Borrowed(path))
}
Expand Down
5 changes: 4 additions & 1 deletion cli/npm/managed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,8 +704,11 @@ impl CliNpmResolver for ManagedCliNpmResolver {
&self,
permissions: &mut dyn NodePermissions,
path: &'a Path,
stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<Cow<'a, Path>, AnyError> {
self.fs_resolver.ensure_read_permission(permissions, path)
self
.fs_resolver
.ensure_read_permission(permissions, path, stack)
}

fn check_state_hash(&self) -> Option<u64> {
Expand Down
4 changes: 3 additions & 1 deletion cli/npm/managed/resolvers/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub trait NpmPackageFsResolver: Send + Sync {
&self,
permissions: &mut dyn NodePermissions,
path: &'a Path,
stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<Cow<'a, Path>, AnyError>;
}

Expand All @@ -87,6 +88,7 @@ impl RegistryReadPermissionChecker {
&self,
permissions: &mut dyn NodePermissions,
path: &'a Path,
stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<Cow<'a, Path>, AnyError> {
if permissions.query_read_all() {
return Ok(Cow::Borrowed(path)); // skip permissions checks below
Expand Down Expand Up @@ -133,7 +135,7 @@ impl RegistryReadPermissionChecker {
}
}

permissions.check_read_path(path).map_err(Into::into)
permissions.check_read_path(path, stack).map_err(Into::into)
}
}

Expand Down
3 changes: 2 additions & 1 deletion cli/npm/managed/resolvers/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,11 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
&self,
permissions: &mut dyn NodePermissions,
path: &'a Path,
stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<Cow<'a, Path>, AnyError> {
self
.registry_read_permission_checker
.ensure_registry_read_permission(permissions, path)
.ensure_registry_read_permission(permissions, path, stack)
}
}

Expand Down
3 changes: 2 additions & 1 deletion cli/npm/managed/resolvers/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,11 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
&self,
permissions: &mut dyn NodePermissions,
path: &'a Path,
stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<Cow<'a, Path>, AnyError> {
self
.registry_read_permission_checker
.ensure_registry_read_permission(permissions, path)
.ensure_registry_read_permission(permissions, path, stack)
}
}

Expand Down
1 change: 1 addition & 0 deletions cli/npm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ pub trait CliNpmResolver: NpmResolver {
&self,
permissions: &mut dyn NodePermissions,
path: &'a Path,
stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<Cow<'a, Path>, AnyError>;

/// Returns a hash returning the state of the npm resolver
Expand Down
7 changes: 5 additions & 2 deletions cli/ops/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::time;
use deno_core::error::generic_error;
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::error::JsStackFrame;
use deno_core::op2;
use deno_core::v8;
use deno_core::ModuleSpecifier;
Expand Down Expand Up @@ -51,15 +52,17 @@ fn op_bench_get_origin(state: &mut OpState) -> String {
#[derive(Clone)]
struct PermissionsHolder(Uuid, PermissionsContainer);

#[op2]
#[op2(reentrant)]
#[serde]
pub fn op_pledge_test_permissions(
state: &mut OpState,
#[serde] args: ChildPermissionsArg,
#[stack_trace] stack: Option<Vec<JsStackFrame>>,
Copy link
Member

@dsherret dsherret Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be nice if we instead stored this internally in the op state then had the ability to register updates to it:

state/worker.on_stack_update(|stack| permissions_container.set_current_stack(stack));

Then in the permissions container it could check what the current registred stack is. That way we don't need to pass this around so much.

) -> Result<Uuid, deno_runtime::deno_permissions::ChildPermissionError> {
let token = Uuid::new_v4();
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
let worker_permissions = parent_permissions.create_child_permissions(args)?;
let worker_permissions =
parent_permissions.create_child_permissions(args, stack)?;
let parent_permissions = parent_permissions.clone();

if state.try_take::<PermissionsHolder>().is_some() {
Expand Down
6 changes: 4 additions & 2 deletions cli/ops/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,17 @@ deno_core::extension!(deno_test,
#[derive(Clone)]
struct PermissionsHolder(Uuid, PermissionsContainer);

#[op2]
#[op2(reentrant)]
#[serde]
pub fn op_pledge_test_permissions(
state: &mut OpState,
#[serde] args: ChildPermissionsArg,
#[stack_trace] stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<Uuid, deno_runtime::deno_permissions::ChildPermissionError> {
let token = Uuid::new_v4();
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
let worker_permissions = parent_permissions.create_child_permissions(args)?;
let worker_permissions =
parent_permissions.create_child_permissions(args, stack)?;
let parent_permissions = parent_permissions.clone();

if state.try_take::<PermissionsHolder>().is_some() {
Expand Down
3 changes: 2 additions & 1 deletion cli/standalone/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ impl NodeRequireLoader for EmbeddedModuleLoader {
&self,
permissions: &mut dyn deno_runtime::deno_node::NodePermissions,
path: &'a std::path::Path,
stack: Option<Vec<deno_core::error::JsStackFrame>>,
) -> Result<Cow<'a, std::path::Path>, AnyError> {
if self.shared.modules.has_file(path) {
// allow reading if the file is in the snapshot
Expand All @@ -420,7 +421,7 @@ impl NodeRequireLoader for EmbeddedModuleLoader {
self
.shared
.npm_resolver
.ensure_read_permission(permissions, path)
.ensure_read_permission(permissions, path, stack)
}

fn load_text_file_lossy(
Expand Down
6 changes: 6 additions & 0 deletions cli/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,9 @@ impl CliMainWorkerFactory {
origin_storage_dir,
stdio,
skip_op_registration: shared.options.skip_op_registration,
enable_stack_trace_arg_in_ops: crate::args::has_flag_env_var(
"DENO_TRACE_PERMISSIONS",
),
};

let mut worker = MainWorker::bootstrap_from_options(
Expand Down Expand Up @@ -792,6 +795,9 @@ fn create_web_worker_callback(
strace_ops: shared.options.strace_ops.clone(),
close_on_idle: args.close_on_idle,
maybe_worker_metadata: args.maybe_worker_metadata,
enable_stack_trace_arg_in_ops: crate::args::has_flag_env_var(
"DENO_TRACE_PERMISSIONS",
),
};

WebWorker::bootstrap_from_options(services, options)
Expand Down
Loading
Loading