diff options
author | Elias Sjögreen <eliassjogreen1@gmail.com> | 2021-08-06 23:28:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-06 23:28:10 +0200 |
commit | 33c8d790c3d358a475c9ba828043e2c19e8d4b37 (patch) | |
tree | 4ab33b3e5b352d49667d55631c76ee76af2ec5e2 /runtime/ops | |
parent | 0d1a522a03c22749e96dab06ca7b3e8b428df701 (diff) |
feat: ffi to replace plugins (#11152)
This commit removes implementation of "native plugins" and replaces
it with FFI API.
Effectively "Deno.openPlugin" API was replaced with "Deno.dlopen" API.
Diffstat (limited to 'runtime/ops')
-rw-r--r-- | runtime/ops/mod.rs | 1 | ||||
-rw-r--r-- | runtime/ops/permissions.rs | 7 | ||||
-rw-r--r-- | runtime/ops/plugin.rs | 86 | ||||
-rw-r--r-- | runtime/ops/worker_host.rs | 43 |
4 files changed, 44 insertions, 93 deletions
diff --git a/runtime/ops/mod.rs b/runtime/ops/mod.rs index 82ccf0506..e08ddd1c0 100644 --- a/runtime/ops/mod.rs +++ b/runtime/ops/mod.rs @@ -6,7 +6,6 @@ pub mod http; pub mod io; pub mod os; pub mod permissions; -pub mod plugin; pub mod process; pub mod runtime; pub mod signal; diff --git a/runtime/ops/permissions.rs b/runtime/ops/permissions.rs index 3395430e4..d9f341633 100644 --- a/runtime/ops/permissions.rs +++ b/runtime/ops/permissions.rs @@ -28,6 +28,7 @@ pub struct PermissionArgs { host: Option<String>, variable: Option<String>, command: Option<String>, + library: Option<String>, } pub fn op_query_permission( @@ -49,7 +50,7 @@ pub fn op_query_permission( ), "env" => permissions.env.query(args.variable.as_deref()), "run" => permissions.run.query(args.command.as_deref()), - "plugin" => permissions.plugin.query(), + "ffi" => permissions.ffi.query(args.library.as_deref()), "hrtime" => permissions.hrtime.query(), n => { return Err(custom_error( @@ -80,7 +81,7 @@ pub fn op_revoke_permission( ), "env" => permissions.env.revoke(args.variable.as_deref()), "run" => permissions.run.revoke(args.command.as_deref()), - "plugin" => permissions.plugin.revoke(), + "ffi" => permissions.ffi.revoke(args.library.as_deref()), "hrtime" => permissions.hrtime.revoke(), n => { return Err(custom_error( @@ -111,7 +112,7 @@ pub fn op_request_permission( ), "env" => permissions.env.request(args.variable.as_deref()), "run" => permissions.run.request(args.command.as_deref()), - "plugin" => permissions.plugin.request(), + "ffi" => permissions.ffi.request(args.library.as_deref()), "hrtime" => permissions.hrtime.request(), n => { return Err(custom_error( diff --git a/runtime/ops/plugin.rs b/runtime/ops/plugin.rs deleted file mode 100644 index cc3bf93d5..000000000 --- a/runtime/ops/plugin.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::permissions::Permissions; -use deno_core::error::AnyError; -use deno_core::op_sync; -use deno_core::Extension; -use deno_core::OpState; -use deno_core::Resource; -use deno_core::ResourceId; -use dlopen::symbor::Library; -use log::debug; -use std::borrow::Cow; -use std::mem; -use std::path::PathBuf; -use std::rc::Rc; - -/// A default `init` function for plugins which mimics the way the internal -/// extensions are initalized. Plugins currently do not support all extension -/// features and are most likely not going to in the future. Currently only -/// `init_state` and `init_ops` are supported while `init_middleware` and `init_js` -/// are not. Currently the `PluginResource` does not support being closed due to -/// certain risks in unloading the dynamic library without unloading dependent -/// functions and resources. -pub type InitFn = fn() -> Extension; - -pub fn init() -> Extension { - Extension::builder() - .ops(vec![("op_open_plugin", op_sync(op_open_plugin))]) - .build() -} - -pub fn op_open_plugin( - state: &mut OpState, - filename: String, - _: (), -) -> Result<ResourceId, AnyError> { - let filename = PathBuf::from(&filename); - - super::check_unstable(state, "Deno.openPlugin"); - let permissions = state.borrow_mut::<Permissions>(); - permissions.plugin.check()?; - - debug!("Loading Plugin: {:#?}", filename); - let plugin_lib = Library::open(filename).map(Rc::new)?; - let plugin_resource = PluginResource::new(&plugin_lib); - - // Forgets the plugin_lib value to prevent segfaults when the process exits - mem::forget(plugin_lib); - - let init = *unsafe { plugin_resource.0.symbol::<InitFn>("init") }?; - let rid = state.resource_table.add(plugin_resource); - let mut extension = init(); - - if !extension.init_js().is_empty() { - panic!("Plugins do not support loading js"); - } - - if extension.init_middleware().is_some() { - panic!("Plugins do not support middleware"); - } - - extension.init_state(state)?; - let ops = extension.init_ops().unwrap_or_default(); - for (name, opfn) in ops { - state.op_table.register_op(name, opfn); - } - - Ok(rid) -} - -struct PluginResource(Rc<Library>); - -impl Resource for PluginResource { - fn name(&self) -> Cow<str> { - "plugin".into() - } - - fn close(self: Rc<Self>) { - unimplemented!(); - } -} - -impl PluginResource { - fn new(lib: &Rc<Library>) -> Self { - Self(lib.clone()) - } -} diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs index 2cd9a14ad..5315ff5c7 100644 --- a/runtime/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs @@ -3,6 +3,7 @@ use crate::permissions::resolve_read_allowlist; use crate::permissions::resolve_write_allowlist; use crate::permissions::EnvDescriptor; +use crate::permissions::FfiDescriptor; use crate::permissions::NetDescriptor; use crate::permissions::PermissionState; use crate::permissions::Permissions; @@ -218,6 +219,26 @@ fn merge_run_permission( Ok(main) } +fn merge_ffi_permission( + mut main: UnaryPermission<FfiDescriptor>, + worker: Option<UnaryPermission<FfiDescriptor>>, +) -> Result<UnaryPermission<FfiDescriptor>, AnyError> { + if let Some(worker) = worker { + if (worker.global_state < main.global_state) + || !worker.granted_list.iter().all(|x| main.check(&x.0).is_ok()) + { + return Err(custom_error( + "PermissionDenied", + "Can't escalate parent thread permissions", + )); + } else { + main.global_state = worker.global_state; + main.granted_list = worker.granted_list; + } + } + Ok(main) +} + pub fn create_worker_permissions( main_perms: Permissions, worker_perms: PermissionsArg, @@ -226,7 +247,7 @@ pub fn create_worker_permissions( env: merge_env_permission(main_perms.env, worker_perms.env)?, hrtime: merge_boolean_permission(main_perms.hrtime, worker_perms.hrtime)?, net: merge_net_permission(main_perms.net, worker_perms.net)?, - plugin: merge_boolean_permission(main_perms.plugin, worker_perms.plugin)?, + ffi: merge_ffi_permission(main_perms.ffi, worker_perms.ffi)?, read: merge_read_permission(main_perms.read, worker_perms.read)?, run: merge_run_permission(main_perms.run, worker_perms.run)?, write: merge_write_permission(main_perms.write, worker_perms.write)?, @@ -241,8 +262,8 @@ pub struct PermissionsArg { hrtime: Option<PermissionState>, #[serde(default, deserialize_with = "as_unary_net_permission")] net: Option<UnaryPermission<NetDescriptor>>, - #[serde(default, deserialize_with = "as_permission_state")] - plugin: Option<PermissionState>, + #[serde(default, deserialize_with = "as_unary_ffi_permission")] + ffi: Option<UnaryPermission<FfiDescriptor>>, #[serde(default, deserialize_with = "as_unary_read_permission")] read: Option<UnaryPermission<ReadDescriptor>>, #[serde(default, deserialize_with = "as_unary_run_permission")] @@ -414,6 +435,22 @@ where })) } +fn as_unary_ffi_permission<'de, D>( + deserializer: D, +) -> Result<Option<UnaryPermission<FfiDescriptor>>, D::Error> +where + D: Deserializer<'de>, +{ + let value: UnaryPermissionBase = + deserializer.deserialize_any(ParseBooleanOrStringVec)?; + + Ok(Some(UnaryPermission::<FfiDescriptor> { + global_state: value.global_state, + granted_list: value.paths.into_iter().map(FfiDescriptor).collect(), + ..Default::default() + })) +} + #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreateWorkerArgs { |