Skip to content

Commit

Permalink
wip: native plugin ops
Browse files Browse the repository at this point in the history
  • Loading branch information
afinch7 committed Nov 18, 2019
1 parent 5671d38 commit 661e5a4
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 0 deletions.
59 changes: 59 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ base64 = "0.11.0"
byteorder = "1.3.2"
clap = "2.33.0"
dirs = "2.0.2"
dlopen = "0.1.8"
futures = { version = "0.3", features = [ "compat", "io-compat" ] }
http = "0.1.19"
hyper = "0.12.35"
Expand Down
15 changes: 15 additions & 0 deletions cli/deno_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub use crate::msg::ErrorKind;
use deno::AnyError;
use deno::ErrBox;
use deno::ModuleResolutionError;
use dlopen::Error as DlopenError;
use http::uri;
use hyper;
use reqwest;
Expand Down Expand Up @@ -287,6 +288,19 @@ mod unix {
}
}

impl GetErrorKind for DlopenError {
fn kind(&self) -> ErrorKind {
use dlopen::Error::*;
match self {
NullCharacter(_) => ErrorKind::Other,
OpeningLibraryError(e) => GetErrorKind::kind(e),
SymbolGettingError(e) => GetErrorKind::kind(e),
NullSymbol => ErrorKind::Other,
AddrNotMatchingDll(e) => GetErrorKind::kind(e),
}
}
}

impl GetErrorKind for dyn AnyError {
fn kind(&self) -> ErrorKind {
use self::GetErrorKind as Get;
Expand Down Expand Up @@ -320,6 +334,7 @@ impl GetErrorKind for dyn AnyError {
.downcast_ref::<serde_json::error::Error>()
.map(Get::kind)
})
.or_else(|| self.downcast_ref::<DlopenError>().map(Get::kind))
.or_else(|| unix_error_kind(self))
.unwrap_or_else(|| {
panic!("Can't get ErrorKind for {:?}", self);
Expand Down
14 changes: 14 additions & 0 deletions cli/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub struct DenoFlags {
pub net_whitelist: Vec<String>,
pub allow_env: bool,
pub allow_run: bool,
pub allow_native: bool,
pub allow_hrtime: bool,
pub no_prompts: bool,
pub no_fetch: bool,
Expand Down Expand Up @@ -105,6 +106,11 @@ fn add_run_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
.long("allow-run")
.help("Allow running subprocesses"),
)
.arg(
Arg::with_name("allow-native")
.long("allow-native")
.help("Allow opening native plugins"),
)
.arg(
Arg::with_name("allow-hrtime")
.long("allow-hrtime")
Expand Down Expand Up @@ -837,6 +843,9 @@ fn parse_run_args(mut flags: DenoFlags, matches: &ArgMatches) -> DenoFlags {
if matches.is_present("allow-run") {
flags.allow_run = true;
}
if matches.is_present("allow-native") {
flags.allow_native = true;
}
if matches.is_present("allow-hrtime") {
flags.allow_hrtime = true;
}
Expand All @@ -847,6 +856,7 @@ fn parse_run_args(mut flags: DenoFlags, matches: &ArgMatches) -> DenoFlags {
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_native = true;
flags.allow_hrtime = true;
}
if matches.is_present("no-fetch") {
Expand Down Expand Up @@ -964,6 +974,7 @@ pub fn flags_from_vec(
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_native = true;
flags.allow_hrtime = true;
let code: &str = eval_match.value_of("code").unwrap();
argv.extend(vec![code.to_string()]);
Expand Down Expand Up @@ -1041,6 +1052,7 @@ pub fn flags_from_vec(
flags.allow_net = true;
flags.allow_env = true;
flags.allow_run = true;
flags.allow_native = true;
argv.push(INSTALLER_URL.to_string());

if install_match.is_present("dir") {
Expand Down Expand Up @@ -1131,6 +1143,7 @@ pub fn flags_from_vec(
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_native = true;
flags.allow_hrtime = true;
argv.push(XEVAL_URL.to_string());

Expand Down Expand Up @@ -1174,6 +1187,7 @@ pub fn flags_from_vec(
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_native = true;
flags.allow_hrtime = true;
DenoSubcommand::Repl
}
Expand Down
1 change: 1 addition & 0 deletions cli/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod fetch;
pub mod files;
pub mod fs;
pub mod io;
pub mod native_plugins;
pub mod net;
pub mod os;
pub mod permissions;
Expand Down
103 changes: 103 additions & 0 deletions cli/ops/native_plugins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use super::dispatch_json::{Deserialize, JsonOp, Value};
use crate::fs as deno_fs;
use crate::ops::json_op;
use crate::state::ThreadSafeState;
use deno::*;
use dlopen::symbor::Library;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::sync::Arc;
use std::sync::Mutex;

pub fn init(
i: &mut Isolate,
s: &ThreadSafeState,
isolate_arc: Arc<Mutex<deno::Isolate>>,
) {
let isolate_arc_ = isolate_arc.clone();
i.register_op(
"open_native_plugin",
s.core_op(json_op(s.stateful_op(move |state, args, zero_copy| {
op_open_native_plugin(&isolate_arc_, state, args, zero_copy)
}))),
);
}

fn open_plugin<P: AsRef<OsStr>>(lib_path: P) -> Result<Library, ErrBox> {
debug!("Loading Native Plugin: {:#?}", lib_path.as_ref());

Library::open(lib_path).map_err(ErrBox::from)
}

struct NativePluginResource {
lib: Library,
ops: Vec<(String, OpId)>,
}

impl Resource for NativePluginResource {}

struct InitContext {
isolate: Arc<Mutex<deno::Isolate>>,
plugin_rid: ResourceId,
ops: Vec<(String, OpId)>,
}

impl PluginInitContext for InitContext {
fn register_op(
&mut self,
name: &str,
op: Box<dyn Fn(&[u8], Option<PinnedBuf>) -> CoreOp + Send + Sync + 'static>,
) -> OpId {
let mut i = self.isolate.lock().unwrap();
let opid = i.register_op(&format!("{}_{}", self.plugin_rid, name), op);
self.ops.push((name.to_string(), opid));
opid
}
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct OpenNativePluginArgs {
filename: String,
}

pub fn op_open_native_plugin(
isolate: &Arc<Mutex<Isolate>>,
state: &ThreadSafeState,
args: Value,
_zero_copy: Option<PinnedBuf>,
) -> Result<JsonOp, ErrBox> {
let args: OpenNativePluginArgs = serde_json::from_value(args)?;
let (filename, filename_) = deno_fs::resolve_from_cwd(&args.filename)?;

state.check_native(&filename_)?;

let lib = open_plugin(filename)?;
let plugin_resource = NativePluginResource {
lib,
ops: Vec::new(),
};
let mut table = state.lock_resource_table();
let rid = table.add("native_plugin", Box::new(plugin_resource));
let plugin_resource = table.get_mut::<NativePluginResource>(rid).unwrap();

let init_fn = *unsafe {
plugin_resource
.lib
.symbol::<PluginInitFn>("native_plugin_init")
}?;
let mut init_context = InitContext {
isolate: isolate.clone(),
plugin_rid: rid,
ops: Vec::new(),
};
init_fn(&mut init_context);
plugin_resource.ops.append(&mut init_context.ops);
let ops: HashMap<String, OpId> = plugin_resource
.ops
.iter()
.map(|record| (record.0.clone(), record.1))
.collect();

Ok(JsonOp::Sync(json!({ "rid": rid, "ops": ops })))
}
9 changes: 9 additions & 0 deletions cli/permissions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ pub struct DenoPermissions {
pub net_whitelist: Arc<HashSet<String>>,
pub allow_env: PermissionAccessor,
pub allow_run: PermissionAccessor,
pub allow_native: PermissionAccessor,
pub allow_hrtime: PermissionAccessor,
}

Expand All @@ -157,6 +158,7 @@ impl DenoPermissions {
net_whitelist: Arc::new(flags.net_whitelist.iter().cloned().collect()),
allow_env: PermissionAccessor::from(flags.allow_env),
allow_run: PermissionAccessor::from(flags.allow_run),
allow_native: PermissionAccessor::from(flags.allow_native),
allow_hrtime: PermissionAccessor::from(flags.allow_hrtime),
}
}
Expand Down Expand Up @@ -300,6 +302,13 @@ impl DenoPermissions {
.request("Deno requests to access to high precision time.")
}

pub fn check_native(&self, filename: &str) -> Result<(), ErrBox> {
self.allow_native.get_state().check(
&format!("access to open a native plugin: {}", filename),
"run again with the --allow-run flag",
)
}

pub fn get_permission_state(
&self,
name: &str,
Expand Down
5 changes: 5 additions & 0 deletions cli/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@ impl ThreadSafeState {
self.permissions.check_run()
}

#[inline]
pub fn check_native(&self, filename: &str) -> Result<(), ErrBox> {
self.permissions.check_native(filename)
}

pub fn check_dyn_import(
self: &Self,
module_specifier: &ModuleSpecifier,
Expand Down
Loading

0 comments on commit 661e5a4

Please sign in to comment.