diff --git a/Cargo.lock b/Cargo.lock index 775f121550..43720fbe09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -942,6 +942,7 @@ dependencies = [ "regex", "ring", "serde", + "signal-hook-registry", "sys-info", "termcolor", "test_util", diff --git a/cli/tests/unit/signal_test.ts b/cli/tests/unit/signal_test.ts index 31562c99a6..b67dc96686 100644 --- a/cli/tests/unit/signal_test.ts +++ b/cli/tests/unit/signal_test.ts @@ -203,3 +203,37 @@ Deno.test( }); }, ); + +Deno.test( + { + ignore: Deno.build.os === "windows", + permissions: { run: true }, + }, + function signalForbiddenSignalTest() { + assertThrows( + () => Deno.addSignalListener("SIGKILL", () => {}), + TypeError, + "Binding to signal 'SIGKILL' is not allowed", + ); + assertThrows( + () => Deno.addSignalListener("SIGSTOP", () => {}), + TypeError, + "Binding to signal 'SIGSTOP' is not allowed", + ); + assertThrows( + () => Deno.addSignalListener("SIGILL", () => {}), + TypeError, + "Binding to signal 'SIGILL' is not allowed", + ); + assertThrows( + () => Deno.addSignalListener("SIGFPE", () => {}), + TypeError, + "Binding to signal 'SIGFPE' is not allowed", + ); + assertThrows( + () => Deno.addSignalListener("SIGSEGV", () => {}), + TypeError, + "Binding to signal 'SIGSEGV' is not allowed", + ); + }, +); diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8733e1727d..3dee3fb4b2 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -75,6 +75,7 @@ once_cell = "=1.9.0" regex = "1.5.4" ring = "0.16.20" serde = { version = "1.0.129", features = ["derive"] } +signal-hook-registry = "1.4.0" sys-info = "0.9.0" termcolor = "1.1.2" tokio = { version = "1.10.1", features = ["full"] } diff --git a/runtime/ops/signal.rs b/runtime/ops/signal.rs index db30c66d88..f260c611c5 100644 --- a/runtime/ops/signal.rs +++ b/runtime/ops/signal.rs @@ -181,8 +181,14 @@ fn op_signal_bind( ) -> Result { super::check_unstable(state, "Deno.signal"); let signo = signal_str_to_int(&sig)?; + if signal_hook_registry::FORBIDDEN.contains(&signo) { + return Err(type_error(format!( + "Binding to signal '{}' is not allowed", + sig + ))); + } let resource = SignalStreamResource { - signal: AsyncRefCell::new(signal(SignalKind::from_raw(signo)).unwrap()), + signal: AsyncRefCell::new(signal(SignalKind::from_raw(signo))?), cancel: Default::default(), }; let rid = state.resource_table.add(resource);