-
Notifications
You must be signed in to change notification settings - Fork 32
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
RFC: Trusted Language Handling #25
Comments
I have a personal bias towards the We noted from some benchmarks and papers that there is some definite speed impact, which I worry about, however creating proper isolation on cdylibs may incur roughly the same overhead... |
I was investigating the dylib method a bit this morning. There exists crates like https://github.com/servo/gaol (created for Servo, but long unmaintained), https://github.com/unrelentingtech/rusty-sandbox (also long unmaintained). I also found this really good article by @marioortizmanero who is(/was?) doing a @tremor-rs LFX internship: https://nullderef.com/blog/plugin-tech/, which also linked to this paper which includes some metrics around inter-process communication options other than WASM. I also saw https://github.com/quantumsheep/godbox, which uses https://github.com/ioi/isolate underneath. This offers some Linux-specific solutions. Godbox doesn't seem appropriate for our needs, but Isolate might be something we have interests in. I also found this paper: https://dl.acm.org/doi/pdf/10.1145/3477113.3487272 which discusses some possibilities on using actual language features to create isolation boundaries, but it mostly describes and proposes mechanisms, and doesn't seem to have existing implementation. |
We've dug into a branch that does execution with wasmtime and it turns out to be quite fast: https://github.com/tcdi/plrust/tree/wasm-execution We're exploring how to manage interfaces like SPI next. (Debug mode) plrust=# DROP EXTENSION IF EXISTS plrust CASCADE; CREATE EXTENSION plrust;
NOTICE: drop cascades to function spi_poc2(text)
DROP EXTENSION
Time: 3.273 ms
CREATE EXTENSION
Time: 3.196 ms
plrust=# CREATE OR REPLACE FUNCTION spi_poc2(a TEXT) RETURNS TEXT IMMUTABLE STRICT LANGUAGE PLRUST AS $$ a.to_string() $$;
INFO: fn25168_2200_235880
CREATE FUNCTION
Time: 4242.268 ms (00:04.242)
plrust=# SELECT spi_poc2('bean');
spi_poc2
----------
bean
(1 row)
Time: 285.885 ms
plrust=# SELECT spi_poc2('bean');
spi_poc2
----------
bean
(1 row)
Time: 1.460 ms
plrust=# SELECT spi_poc2('bean');
spi_poc2
----------
bean
(1 row)
Time: 1.391 ms
plrust=# |
Tasks
|
In general preventing I'd think spawning a sandboxed process (seccomp filter on Linux, seatbelt on macOS, ...) to run the function would be able to limit the damage to what that process has access to (if we can arrange that to be less, that would be ideal). I'm not terribly familiar with sandboxing on Linux though, and maybe either seccomp isn't strong enough2, or it may be there's no way to limit the damage, since they still need the ability to talk to the db. Either way, I'm assuming this isn't quite enough given the mention that we'd still need to prevent FWIW, WebAssembly (via Footnotes
|
From some offline discussion: trying to protect from malicious actors in cases like this is not (currently) within the scope of this project (or issue), so this is fine. Maybe someday it will be revisited, but it's an impractical amount of work at the moment, and not needed. |
We've moved past the idea of WASM (for now) and a trusted plrust can be built with |
As highlighted by @jim-mlodgenski in #9, PL/Rust is currently an "Untrusted" language. This is mostly due to immaturity of the project.
It's our intent to provide a "Trusted" language handler with this repo. For a review of the distinction between trusted and untrusted, see the PostgreSQL PL/Perl docs.
PL/Rust should be restricted from using certain operations such as:
Rust is a bit different
Rust is considerably different than Perl, Python, Node (via PL/v8) in that it is not interpreted, nor does it have a runtime we can embed in PL/Rust.
Rust creates either target-specific shared objects or binaries, or it creates portable
wasm
artifacts.The shared objects (or binaries) are roughly equivalent to C code, and get executed as such. Due to it's nature, Rust also naturally includes abundant unsafe support, unlike these other interpreted languages. A Rust function from a shared library can do as it pleases with the memory of the process, for example.
PL/Rust's current handling
At this time, PL/Rust is loaded as a PostgreSQL extension, and inside of that process it finds and dyloads the produced
cdylib
.Doing this, library initialization routines occur, and all normal precautions around calling unknown foreign functions must be followed. In general, this process is not trusted.
Since PL/Rust created libraries are ultimately loaded by the
postmaster
binary, they can do whatever any otherpgx
extension can do, or anyC
function.Ways forward
Ultimately, there are two paths we've been discussing:
#[forbid(unsafe)]
and disablingstd
, ensuring users only usecore
andalloc
, along with other allowlisted also#[no_std]
crates (so the user cannot simplyextern crate std;
.wasmtime
(or some other runtime) and use wasm's sandboxing features from inside the postmaster process. (Note this path does not require any disallowing of unsafe code, as the function will already be sandboxed, so it's free to do whatever it wants to it's memory.)There are several factors contributing to a decision:
The text was updated successfully, but these errors were encountered: