bytecodealliance / lucet Goto Github PK
View Code? Open in Web Editor NEWLucet, the Sandboxing WebAssembly Compiler.
License: Apache License 2.0
Lucet, the Sandboxing WebAssembly Compiler.
License: Apache License 2.0
I'm interested in using Lucet for a project, but I have security concerns with running user-provided code (of course). I think it would be very useful if you could provide a description of the sandboxing method you use for Terrarium, or even provide some example code that shows how you're sandboxing the user code so it can't consume the whole CPU.
In #44 we use wasmparser to validate the entire module before using it via cranelift-wasm to parse, without validating, the module and functions.
This PR to wasmparser makes it possible to validate the functions at parse time:
https://github.com/yurydelendik/wasmparser.rs/pull/100
Perhaps this change actually belongs upstream in cranelift-wasm, we can figure it out once #44 is merged and we get to it.
In #44, I had to comment out a bunch of tests because the information is not available from lucetc with the new set of abstractions.
Most (maybe all) of that information should become available as part of the lucet-module (currently still known as lucet-module-data) work. As it becomes available, the tests should be re-enabled.
Hi ... What are the steps for building and running shootout with sightglass? Also, can you elaborate on the description that says that sightglass it is for testing "various versions" of the Lucet toolchain?
Sightglass ships with a set of microbenchmarks called shootout. The scripts to build the shootout tests with native and various versions of the Lucet toolchain are in /benchmarks/shootout.
Some context: As far as I understand the docker container contains one version of Lucet. I've been able to run and time my own simple fib example that I copied to the container. Sightglass and Lucet readmes though talk about comparing multiple shared libraries and versions of the Lucet toolchain. What does that goal mean in this context of having one Lucet instance running?
Also when trying to build Sightglass in docker I got this error:
root@yshou-mint:/lucet/sightglass# cargo run
Compiling proc-macro2 v0.4.27
Compiling num-traits v0.2.6
Compiling unicode-xid v0.1.0
Compiling semver-parser v0.7.0
Compiling cc v1.0.31
Compiling libc v0.2.50
Compiling syn v0.15.29
Compiling num-integer v0.1.39
error: couldn't create a temp dir: No such file or directory (os error 2) at path "/tmp/rustcVkLQ6h"
error: aborting due to previous error
error: Could not compile `unicode-xid`.
warning: build failed, waiting for other jobs to finish...
Is sightglass meant to run in docker?
Also separately, I noticed a benchmark folder on host with a shootout directory and a makefile. I could not get the make command to build, but is this intended to be used if Lucet is running in docker and not on host? How does this folder relate to the base sightglass folder which also contains a shootout directory with the actual kernels included?
Thanks
The main README
file just gives the big picture, yet it is way too long.
The quickstart instructions difficult to find. Other README
files are hidden in subfolders.
Not sure that anybody has noticed the document about Lucet's security model.
Maybe we should consider moving all the documentation to the Wiki section, so that everything can be at the same place, and people can quickly get the info they are looking for.
Consider the following code:
(module
(memory 1)
(global $memoryBase i32 (i32.const 0))
(data
(global.get $memoryBase)
"abcd")
(func $main (nop))
(export "_start" (func $main))
)
Attempting to compile with lucetc-wasi has the following results (shows from .wat followed by from .wasm):
# lucetc-wasi wasitests/data_global_offset.wat -o wasitests/data_global_offset.so
Error(Validate("test.wast:6:6: error: initializer expression can only reference an imported global\n (global.get $memoryBase)\n ^^^^^^^^^^\n"))
# wasm-as wasitests/data_global_offset.wat -o wasitests/data_global_offset.wasm
# lucetc-wasi wasitests/data_global_offset.wasm -o wasitests/data_global_offset.so
LucetcError { inner: ErrorMessage { msg: "cannot create sparse data: data initializer uses global as base" }
Unsupported }
wasm-as has no problem compiling the module and wasmtime has no problem running the resulting module.
We of course don't need to adopt the suggestions whole cloth, but we should see whether we can get a good signal-to-noise ratio coming from Clippy.
In #104, a user struggled with configuring lucet-wasi to use the release llvm 8 toolchain with the wasi-sdk provided sysroot.
We should support using the wasi-sdk sysroot with whatever toolchain the user wants.
Hi,
I was reading the blog announcement (https://www.fastly.com/blog/announcing-lucet-fastly-native-webassembly-compiler-runtime) that mentioned the instantiation times for wasm modules was under 50 microseconds. This is referring to a single instance of lucet runtime being able to load and instantiate a wasm module in 50 microseconds? I was wondering then how to have multiple instances of a wasm module running to duplicate this. Do you have any pointers here? I am running using the docker script.
lucet appears to assume that a wasm module exports a "_start" function. This should either be optional or dropped since (start ...) is already supported and is called before the exported "_start" routine.
The following wat file:
(module
(memory 256)
(export "memory" (memory 0))
(import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
;; __wasi_ciovec_t struct
(data (i32.const 0) "\08\00\00\00") ;; buf: pointer to hello string
(data (i32.const 4) "\0c\00\00\00") ;; buf_len: 12 characters
;; string
(data (i32.const 8) "hello world\n")
(func $main
(drop (call $fd_write (i32.const 1) (i32.const 0) (i32.const 1) (i32.const 64)))
)
(start $main)
;;(export "_start" $main)
)
Will result in the following:
# RUST_BACKTRACE=1 /opt/lucet/bin/lucet-wasi wasitests/start.so
hello world
thread 'main' panicked at 'lucet-wasi runtime error: Symbol not found: _start', lucet-wasi/src/main.rs:196:23
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:70
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:58
at src/libstd/panicking.rs:200
3: std::panicking::default_hook
at src/libstd/panicking.rs:215
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:478
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:385
6: std::panicking::begin_panic_fmt
at src/libstd/panicking.rs:340
7: lucet_wasi::main
8: std::rt::lang_start::{{closure}}
9: std::panicking::try::do_call
at src/libstd/rt.rs:49
at src/libstd/panicking.rs:297
10: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:92
11: std::rt::lang_start_internal
at src/libstd/panicking.rs:276
at src/libstd/panic.rs:388
at src/libstd/rt.rs:48
12: main
13: __libc_start_main
14: _start
Note that the function specified by (start) is being called and then the exception is thrown. If both (start) and exported "_start" are used (uncomment export above) then the main function is executed twice as follows:
# RUST_BACKTRACE=1 /opt/lucet/bin/lucet-wasi wasitests/start.so
hello world
hello world
I think lucet should not require "_start" to be exported since this functionality is already supported by the standard (start) mechanism.
If this step is done with clang
, they work, but we don't have clang
in devenv
: https://github.com/fastly/lucet/blob/master/benchmarks/shootout/Makefile#L98
Support for these is not landing in #16, but we would eventually like all of the module metadata to live in that structure.
The main challenge here will be keeping the amount of copying down, since the trap metadata is potentially quite large. To that end, we'll probably want to keep at least the tables, but potentially also the manifest as a byte slice to allow zero-copy deserialization. We'll want to be very careful with alignment when we do that.
I'm seeing two errors in building master from source.
Running cargo build --all --release --bins --lib
now generates the following error.
warning: unused import: `siginfo_ext::SiginfoExt`
--> lucet-runtime/lucet-runtime-internals/src/instance/signals.rs:3:5
|
3 | siginfo_ext::SiginfoExt, FaultDetails, Instance, State, TerminationDetails, CURRENT_INSTANCE,
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
warning: unused import: `crate::instance::siginfo_ext::SiginfoExt`
--> lucet-runtime/lucet-runtime-internals/src/instance.rs:10:5
|
10 | use crate::instance::siginfo_ext::SiginfoExt;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> lucet-runtime/lucet-runtime-internals/src/instance.rs:842:25
|
842 | siginfo.si_addr()
| ^^^^^^^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> lucet-runtime/lucet-runtime-internals/src/instance/signals.rs:192:55
|
192 | && !inst.alloc.addr_in_heap_guard(siginfo.si_addr());
| ^^^^^^^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0133`.
error: Could not compile `lucet-runtime-internals`.
warning: build failed, waiting for other jobs to finish...
error: build failed
The second issue is stranger. When I run make build
it launches minimalist Go framework on port 8080 and just sits there. Very strange.
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.1.5
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
โจ http server started on [::]:8080
I want to try to use lucet in my project
but I need know the status of supporting WebAssembly 1.0
if not fully supported, can I find the list of points not supported anywhere?
If a Rust function inside a hostcall panics, rust_panic
will fail to unwind the stack, and instead abort the entire process:
Thread 5 "entrypoint_call" received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffff653f700 (LWP 15853)]
0x00007ffff6e81428 in __GI_raise (sig=sig@entry=6)
at ../sysdeps/unix/sysv/linux/raise.c:54
54 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007ffff6e81428 in __GI_raise (sig=sig@entry=6)
at ../sysdeps/unix/sysv/linux/raise.c:54
#1 0x00007ffff6e8302a in __GI_abort () at abort.c:89
#2 0x0000555556f74f97 in std::sys::unix::abort_internal::h261e63c8f66a8ecb ()
at src/libstd/sys/unix/mod.rs:157
#3 0x0000555556f62871 in std::sys_common::util::abort::h29d205fd0c28488f ()
at src/libstd/sys_common/util.rs:19
#4 0x0000555556f647fa in rust_panic () at src/libstd/panicking.rs:529
#5 0x0000555556f646b2 in std::panicking::rust_panic_with_hook::h744417edfe714d72
() at src/libstd/panicking.rs:498
#6 0x0000555556f640f2 in std::panicking::continue_panic_fmt::h3557b3c3fa21b47b ()
at src/libstd/panicking.rs:385
#7 0x0000555556f63fd6 in rust_begin_unwind () at src/libstd/panicking.rs:312
#8 0x0000555556f8d97d in core::panicking::panic_fmt::h74ee8034b317ceed ()
at src/libcore/panicking.rs:85
#9 0x0000555555e9efd0 in core::result::unwrap_failed::h1774190b7208f8c0 (msg=...,
error=...)
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libcore/macros.rs:16
#10 0x0000555555e9e794 in _$LT$core..result..Result$LT$T$C$$u20$E$GT$$GT$::expect::h03adf3ecff49dadc (self=..., msg=...)
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libcore/result.rs:825
#11 0x0000555555e9ae34 in callback_hostcall (vmctx=0x7ffddffdb000, cb_idx=1, x=0)
at <::lucet_runtime_tests::entrypoint::entrypoint_tests macros>:210
#12 0x00007ffff613e727 in guest_func_callback_entrypoint ()
from /tmp/.tmptdOyeU/out.so
#13 0x00007ffddffdb000 in ?? ()
#14 0x000103f056de8f90 in ?? ()
#15 0x00007fffdfffaff0 in ?? ()
#16 0x0000555556de8fa0 in lucet_context_bootstrap ()
at src/context/context_asm.S:45
#17 0x00007ffddffda040 in ?? ()
#18 0x00007ffff653f480 in ?? ()
#19 0x0000000000000000 in ?? ()
This is currently a stub; it needs to be better
It would be nice to document how to build this project for developers using Windows.
I'm not sure what all the scripts are doing yet but the project at least builds with cargo build --all --release --bins --lib
under WSL/Ubuntu 18.04.2
after having followed the steps in the Dockerfile
.
It should be possible to use Docker for Windows via Hyper-V. If there is interest, I could try to write some equivalent powershell scripts to make this easier.
When trying to compile using make build
on macOS, the Rust component compiles successfully however the following fails.
make -C lucet-builtins
cc --std=gnu99 -Ofast -Wall -Werror -march=native -fPIC -I../lucet-runtime/include -c src/memcpy.c -o build/memcpy.o
In file included from src/memcpy.c:1:
In file included from src/common.h:8:
In file included from ../lucet-runtime/include/lucet.h:9:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/ucontext.h:43:2: error: The deprecated ucontext routines require _XOPEN_SOURCE to be defined
#error The deprecated ucontext routines require _XOPEN_SOURCE to be defined
^
1 error generated.
make[1]: *** [build/memcpy.o] Error 1
make: *** [build] Error 2
macOS 10.14 Mojave with
clang --version
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
I get the following error when trying to run my wasm app:
$ lucet-wasi demo.so
thread 'main' panicked at 'instance can be created: LimitsExceeded("heap spec initial size: HeapSpec { reserved_size: 4194304, guard_size: 4194304, initial_size: 1114112, max_size: None }")', src/libcore/result.rs:997:5
It indeed requires much more memory than that, how do I allow it to allocate more?
update: it seems that limits are specified during the compilation. I've tried to set them to 1 Gb:
lucetc --reserved-size 1073741824 --guard-size 1073741824 pedersen_demo_bg.wasm -o demo.so
But I still get the same error
This flag used to keep temporary files around for debugging, but the code that used it got deleted in a refactor. It should be used to keep the object file around emitting a shared object, and any other intermediate files that get implemented in the future.
Thanks @zhuowei :)
lucet-analyze
is semi-broken since the introduction of module-data and various other minor changes. Once #20 is done, we should use module-data to clean up the lucet-analyze code and release it.
I discovered a backtrace when calling call_indirect
in a much more complicated program but simplified it down to the following reproducer:
(module $calli
(table funcref (elem $fn0 $fn1))
;; Must have a function before the types to trigger the issue
(func $early_fn (param $arg i32) (result i32) (i32.const 0))
(type $fnT0 (func (param i32) (result i32)))
(type $fnT1 (func (result i32)))
(func $fn0 (param $arg i32) (result i32) (i32.const 0))
(func $fn1 (result i32) (i32.const 0))
(func $main0 (drop (call_indirect (type $fnT0) (i32.const 0) (i32.const 0))))
(func $main1 (drop (call_indirect (type $fnT1) (i32.const 1))))
;; This causes a backtrace
(export "_start0" (func $main0))
;; This does not cause a backtrace
(export "_start1" (func $main1))
;; Default _start (for wasmtime)
(export "_start" (func $main0))
)
Here is how the problem manifests:
$ /opt/lucet/bin/lucetc-wasi -o calli.so calli.wasm
$ RUST_BACKTRACE=1 /opt/lucet/bin/lucet-wasi --entrypoint _start0 calli.so
thread 'main' panicked at 'lucet-wasi runtime error: Runtime fault: FaultDetails { fatal: false, trapcode: Some(BadSignature), rip_addr: 139639523104562, rip_addr_details: Some(AddrDetails { in_module_code: true, file_name: Some("/mal/wasm/calli.so"), sym_name: Some("guest_func__start0") }) }', lucet-wasi/src/main.rs:196:23
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:70
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:58
at src/libstd/panicking.rs:200
3: std::panicking::default_hook
at src/libstd/panicking.rs:215
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:478
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:385
6: std::panicking::begin_panic_fmt
at src/libstd/panicking.rs:340
7: lucet_wasi::main
8: std::rt::lang_start::{{closure}}
9: std::panicking::try::do_call
at src/libstd/rt.rs:49
at src/libstd/panicking.rs:297
10: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:92
11: std::rt::lang_start_internal
at src/libstd/panicking.rs:276
at src/libstd/panic.rs:388
at src/libstd/rt.rs:48
12: main
13: __libc_start_main
14: _start
$ RUST_BACKTRACE=1 /opt/lucet/bin/lucet-wasi --entrypoint _start1 calli.so
$ wasmtime calli.wasm
Note that calling the _start1
entrypoint doesn't not cause the problem only calling _start0
will trigger the problem. Also, wasmtime is able to call the _start1
entrypoint without issue.
The problem appears to be triggered by a combination of two things. The first is a call_indirect
call that has an argument to use with the called function (_start0
). Using call_indirect without the argument does not trigger the issue (_start1
). The second necessary part to trigger this is that there must be a function (early_fn
) declared prior to the definition of the two types. If that function is omitted or moved below the type definition then the problem does not reproduce.
I'm having a really difficult time building lucet-wasi
on Arch Linux.
After reading #78 I installed the dependencies I could (hwloc, llvm, lld using pacman), and I also tried my best to install wasi-sdk, which wouldn't compile no matter how much I tried, so I had to take the .deb and use debtap to create an arch pkg.
The commands I ran were:
git clone --recurse-submodules [email protected]:fastly/lucet.git
cd lucet/lucet-wasi
cargo build
I also tried cargo +nightly build --verbose
. I've done a lot more than this, but I'm trying to pare the noise down. I'm out of things I know how to try.
A couple screenshots that might help... Errors with cargo build
:
Errors building wasi-sdk
:
Any help is appreciated...
The max heap size defaults to 1 MB:
fn default() -> Limits {
Limits {
heap_memory_size: 16 * 64 * 1024,
heap_address_space_size: 0x200000000,
stack_size: 128 * 1024,
globals_size: 4096,
}
}
We don't seem to ever set it to what is stored in the wasm module, effectively limiting all applications to 1 MB.
lld
support is not a high priority right now, but this failure might be an indication that we're doing something weird when making object files.
Tested with lld-6
and lld-8
on Ubuntu 18.04.
Hi ... Is it the case that the metric for all tests in shoot out is elapsed time? When I see results below should I assume that any ratio number above the reference of 1 means that shootout test took longer with the c->wasm->native path than the reference path of c->native?
On my system I see a few tests were the c->wasm->native is actually reporting a ratio number below 1. Does this mean those benchmarks performed better when converted to WASM? Where are the raw numbers and binaries used to collect the numbers stored?
Test | Implementation | Ratio | Median | RSD
------------+----------------+--------------------+--------------+--------------------
ackermann | Reference | 1 | 523107 | 10.76839249381212
ackermann | lucet | 2.6516361035666582 | 1456198 | 4.788126703819359
base64 | Reference | 1 | 176240154.5 | 2.916611227769061
base64 | lucet | 1.464050958766964 | 264776860.5 | 4.060475088333558
ctype | Reference | 1 | 277633475.5 | 4.125341827565504
ctype | lucet | 2.827206041953314 | 785632288 | 5.859557592784653
ed25519 | Reference | 1 | 830979983 | 1.7771897005923085
ed25519 | lucet | 7.705137365616381 | 6466526145 | 0
Thanks!
When I try and clone and build lucet I get the following error (long sections elided):
$ git clone --recursive https://github.com/fastly/lucet
$ cd lucet
$ source devenv_setenv.sh
...
Compiling tinytemplate v1.0.1
Compiling sightglass v0.1.0 (/lucet/sightglass)
Compiling criterion v0.2.11
Compiling faerie v0.9.1 (/lucet/faerie)
Compiling lucet-runtime v0.1.0 (/lucet/lucet-runtime)
error: linking with `cc` failed: exit code: 1
|
= note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/lucet/target/release/deps/sightglass-2cd052b5674c317c.sightglass.6anse34c-cgu.0.rcgu.o".................................................................... "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-8895b32baedb08c6.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-6a9d233d01acc350.rlib" "-Wl,--end-group" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-851bb3b5f6c4db49.rlib" "-Wl,-Bdynamic" "-ldl" "-lhwloc" "-lutil" "-lutil" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil" "-rdynamic"
= note: /usr/bin/ld: cannot find -lhwloc
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: Could not compile `sightglass`.
warning: build failed, waiting for other jobs to finish...
error: build failed
Makefile:11: recipe for target 'build' failed
make: *** [build] Error 101
Cleaning
make -C benchmarks/shootout clean
make[1]: Entering directory '/lucet/benchmarks/shootout'
rm -rf build
make[1]: Leaving directory '/lucet/benchmarks/shootout'
make -C lucet-builtins clean
make[1]: Entering directory '/lucet/lucet-builtins'
rm -rf build
make[1]: Leaving directory '/lucet/lucet-builtins'
cargo clean
Tagging the new image
sha256:2ef05992f8b74f20d6eb7a2d64f843c8d9124f7571cae0c7196bf895ffae2a1c
Cleaning
lucet-dev
lucet-dev
Done
$
Perhaps a missing build dep somewhere?
Given the news lately, it would be good to have an alternative to Travis ready to go.
The fastly/lucet
image on Docker Hub is currently manually pushed by @jedisct1. We should automate and document its existence.
After #44 lands, the wasmonkey
crate is the only place in lucetc
where we use the parity-wasm
WebAssembly Module representation. This means we're incurring extra deps, and deserializing & serializing the module, for what is now a much simpler concept to implement than it was way back when wasmonkey
was created.
It should be possible to implement the logic behind builtins entirely in the ModuleDecls::declare_funcs
function, rather than use wasmonkey.
Before the refactor to use cranelift-wasm
(#44), lucetc would use the name section in a WebAssembly module to give more useful object file symbol names to non-exported functions.
Currently, lucetc uses cranelift-wasm
's ModuleEnvironment
trait to parse sections out of a WebAssembly module, but ModuleEnvironment
does not expose any name sections it comes across. We could either patch ModuleEnvironment
to support name sections, or we could stop using ModuleEnvironment
/cranelift_wasm::translate_module
, and just create a ModuleInfo
by using wasmparser
directly.
1f5839b adds a test in entrypoint
to reach an exported import by its export name, which is something we ought to support, but don't. oops.
Related, if (import "env" "add_4_hostcall" (func $add_4_hostcall (param i64 i64 i64 i64)))
is also added before the export
it produces a duplicate import of add_4_hostcall
, and throws off all tests on that module by having function pointers off by one with respect to function indices.
These two can probably grow into a wider set of runtime tests around import/export support as that grows (for globals, memory, ..)
I ran:
git submodule init && git submodule update
source devenv_setenv.sh
but the script fails after it has built the Docker image as follows:
Step 8/8 : ENV WASI_SDK /opt/wasi-sdk
---> Running in 7166b7ae9169
---> 2c45e410f430
Removing intermediate container 7166b7ae9169
Successfully built 2c45e410f430
unknown flag: --mount
See 'docker run --help'.
unknown shorthand flag: 'w' in -w
See 'docker exec --help'.
Lucet hasn't been installed yet... installing...
unknown shorthand flag: 'w' in -w
See 'docker exec --help'.
unknown shorthand flag: 'w' in -w
See 'docker exec --help'.
Unable to run commands in the container
I am using the Docker version ships with Fedora 29, which seems to be too old:
$ docker --version
Docker version 1.13.1, build 1185cfd/1.13.1
Lack of --mount
command line option is easy to work around with:
diff --git a/devenv_start.sh b/devenv_start.sh
index c69f798..d77e696 100755
--- a/devenv_start.sh
+++ b/devenv_start.sh
@@ -11,7 +11,7 @@ if docker ps -f name=lucet | grep -Fq lucet ; then
exit 1
fi
-docker run --name=lucet --detach --mount type=bind,src="$(cd $(dirname ${0}); pwd -P),target=/lucet" \
+docker run --name=lucet --detach -v "$(cd $(dirname ${0}); pwd -P):/lucet:z" \
lucet-dev:latest /bin/sleep 99999999 > /dev/null
if [ -z "$DEVENV_NO_INSTALL" ]; then
I am not sure what is needed to work around the missing -w
option, though.
The current implementations of __wasi_clock_*
delegate to the host system's clock_getres
and clock_gettime
. For untrusted code, it would be useful to limit the precision of these clocks to reduce the potential impact of side channels. Furthermore, the CLOCK_*_CPUTIME_ID
clocks currently give timings for the host process, but a measure of the guest instance runtime would be more accurate and would leak less information.
The lucet-runtime
and lucet-wasi
C APIs currently have minimal/no documentation. Now that they're no longer generated, we can spiff them up more easily.
sigstacks map to threads, not to instances, so we could save a bit of space in the instance memories by moving sigstacks to thread-local storage.
Right now, almost all use of lucetc
is via the command line. For testing purposes and potentially other applications, it would be nice to use lucetc
as a library instead.
A concrete outcome of this would be to no longer use lucetc
in the Makefile targets for generating test guests.
Augmenting this with something that could replace lucetcc
would also be nice, but the API surface of a C compiler is much bigger to bite off.
I have a WASM file that has extra data segments, and Lucet compiles it into an invalid .so file.
I'm using a slightly modified Lucet that adds stub functions for the unimplemented parts of WASI, but I don't think that's causing the issue here.
$ /opt/lucet/bin/lucetc-wasi -o hello.so hello.wasm
$ /opt/lucet/bin/lucet-wasi hello.so
thread 'main' panicked at 'module can be loaded: ModuleError(IncorrectModule("error loading required symbol `lucet_module_data`: /home/zhuowei/swift-source/build/Ninja-RelWithDebInfoAssert/swift-linux-x86_64/bin/hello.so: undefined symbol: lucet_module_data"))', src/libcore/result.rs:997:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
objdump -T hello.so
shows that the symbol is defined, but doesn't have a section:
0000000000000000 g DO *ABS* 00000000000c0745 lucet_module_data
objdump -x hello.so
shows that the entire .data section is missing:
hello.so: file format elf64-x86-64
hello.so
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x00000000003d58b0
Program Header:
LOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
filesz 0x00000000010a9968 memsz 0x00000000010a9968 flags r-x
LOAD off 0x00000000010a9f40 vaddr 0x00000000012a9f40 paddr 0x00000000012a9f40 align 2**21
filesz 0x00000000000000c0 memsz 0x00000000000000c0 flags rw-
DYNAMIC off 0x00000000010a9f40 vaddr 0x00000000012a9f40 paddr 0x00000000012a9f40 align 2**3
filesz 0x00000000000000c0 memsz 0x00000000000000c0 flags rw-
RELRO off 0x00000000010a9f40 vaddr 0x00000000012a9f40 paddr 0x00000000012a9f40 align 2**0
filesz 0x00000000000000c0 memsz 0x00000000000000c0 flags r--
Dynamic Section:
HASH 0x0000000000000120
GNU_HASH 0x000000000002c1e8
STRTAB 0x0000000000108420
SYMTAB 0x0000000000060240
STRSZ 0x00000000002cd482
SYMENT 0x0000000000000018
Sections:
Idx Name Size VMA LMA File off Algn
0 .hash 0002c0c4 0000000000000120 0000000000000120 00000120 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .gnu.hash 00034054 000000000002c1e8 000000000002c1e8 0002c1e8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .dynsym 000a81e0 0000000000060240 0000000000060240 00060240 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynstr 002cd482 0000000000108420 0000000000108420 00108420 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .text 00cd40b6 00000000003d58b0 00000000003d58b0 003d58b0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
5 .eh_frame 00000000 00000000010a9968 00000000010a9968 010a9968 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynamic 000000c0 00000000012a9f40 00000000012a9f40 010a9f40 2**3
CONTENTS, ALLOC, LOAD, DATA
While I'm reasonably sure that my WASM file is corrupt in some way, I think Lucet should still raise an error or something instead of generating a malformed .so file.
https://github.com/fastly/lucet/blob/d0f07b5dc2a7cfa8a9dbc4906b5a6505de69bb52/Dockerfile#L1
why old version? All docker images with a LTS Ubuntu base use bionic.
I'm on a Linux system and would prefer to avoid using Docker to run lucet. I tried to build from source with the following approach:
git clone --recurse-submodules https://github.com/fastly/lucet
make build
This results in an error:
error: linking with `cc` failed: exit code: 1
|
= note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.0.rcgu.o" "/home/mode
ration/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.1.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.10.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228
cb2b6.sightglass.7osejg0u-cgu.11.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.12.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.13.rcgu.o" "/home/moderation/Library/
rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.14.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.15.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightgla
ss.7osejg0u-cgu.2.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.3.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.4.rcgu.o" "/home/moderation/Library/rust/lucet/target
/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.5.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.6.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.7.r
cgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.8.rcgu.o" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.sightglass.7osejg0u-cgu.9.rcgu.o" "-o" "/home/moderation/Library/rust/lucet/target/release/deps/
sightglass-04fd101e228cb2b6" "/home/moderation/Library/rust/lucet/target/release/deps/sightglass-04fd101e228cb2b6.2o7lcldko4bdut5u.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-L" "/home/moderation/Library/rust/lucet/target/release/deps" "-L" "/home/moderation/Li
brary/rust/lucet/target/release/build/backtrace-sys-4373fee90d304fb2/out" "-L" "/home/moderation/Library/rust/lucet/target/release/build/libloading-5fe541c3d4151e79/out" "-L" "/home/moderation/Library/rust/lucet/target/release/build/precision-496cc7c362d78080/out" "-L" "/home/moderation/.rustup/toolchains/
stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/moderation/Library/rust/lucet/target/release/deps/libxfailure-f7dc90dfd4a9cfd5.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libtoml-ac1a3ef5aeb80c15.rlib" "/home/moderation/Library/rust/lucet/t
arget/release/deps/libserde_json-63f87dd33e6bce8d.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libryu-af2123bfcf3608cd.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libitoa-26c13f740021f8ea.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libserde-7a83b69834
8f5de5.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libprinttable-0a003ee6ba7f7f15.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libprecision-a4018824169869a7.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/liblibloading-d6f3c4fec9bf52f3.rlib" "/home/modera
tion/Library/rust/lucet/target/release/deps/libhwloc-d657955c6ca85f56.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libnum-75a8bf3ce92984e1.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libnum_iter-844bcbdbaaa61f8d.rlib" "/home/moderation/Library/rust/lucet/target/release/
deps/libnum_integer-4a85dd3863e35435.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libnum_traits-b8074bac42b59644.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/liberrno-a9cb892deb746a5d.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libbitflags-a827fb3be421
dd97.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libgoblin-17e817d1bcac257c.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/liblog-fb2e40e31efa0e32.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libscroll-749585d9e9a4aa11.rlib" "/home/moderation/Library/rus
t/lucet/target/release/deps/libplain-8436f1bb1b42e0e9.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libfailure-e037ddf141d6ff3e.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libbacktrace-686e3dc254ad0018.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libbac
ktrace_sys-bb5de07908502906.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/librustc_demangle-d56ee7e0a9c7b359.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libcfg_if-46e245e795481900.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libclap-2343a924179041e0.rli
b" "/home/moderation/Library/rust/lucet/target/release/deps/libvec_map-5235e50be5cc1655.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libtextwrap-ad38c5f14ba6a11f.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libunicode_width-ed75cfdbba843d77.rlib" "/home/moderation/Librar
y/rust/lucet/target/release/deps/libstrsim-d9cd59ec4e8643bd.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libbitflags-f8c35c8d20e404a0.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libatty-607e1378b417c701.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libl
ibc-7c518ca6b5574f82.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libansi_term-c769de444c66ce30.rlib" "/home/moderation/Library/rust/lucet/target/release/deps/libbencher-72d41b2cb15a6029.rlib" "-Wl,--start-group" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rus
tlib/x86_64-unknown-linux-gnu/lib/libstd-e39317eb74365d3c.rlib" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-4d55a38564aae54a.rlib" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknow
n-linux-gnu/lib/libbacktrace_sys-f8521075e248b627.rlib" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-7c91ffdc8da860d3.rlib" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/li
b/librustc_demangle-0ad27b9879d551d3.rlib" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-588f18eae3ea58be.rlib" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-4ebf
5caee903d98f.rlib" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-8895b32baedb08c6.rlib" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-6a9d233d0
1acc350.rlib" "-Wl,--end-group" "/home/moderation/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-851bb3b5f6c4db49.rlib" "-Wl,-Bdynamic" "-ldl" "-lhwloc" "-lutil" "-lutil" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-l
util" "-lutil"
= note: /usr/bin/ld: cannot find -lhwloc
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: Could not compile `sightglass`.
warning: build failed, waiting for other jobs to finish...
error: build failed
Makefile:11: recipe for target 'build' failed
make: *** [build] Error 101
I couldn't find any similar issues via search. I'm using Xubuntu 18.04, gcc 8.2.0, clang 7.0.1, ld 2.30. Any ideas would be appreciated.
When an execution of a Lucet instance begins, we context switch off the host stack and onto a stack that is colocated next to the instance's heap. When that execution makes a host-call, we do not switch back to the host stack, but rather remain on the guest stack.
This leaves us in the following position:
The amount of guest stack remaining is a guest-defined property when the guest makes a host-call. Stack overflows while in host code are fatal to the embedding process.
Not good.
So, we propose the following:
Host-calls switch back to the host stack. This isn't as heavyweight as the full context-switch as defined in https://github.com/fastly/lucet/blob/master/lucet-runtime/lucet-runtime-internals/src/context/context_asm.S. We should really only need to save and restore the stack pointer to make this work.
For clarity: This doesn't prevent stack overflows in host-calls from being fatal, but it does prevent it from being reliant upon how much stack the guest has used.
We might want to save embedders the overhead of using Val
, so we should add another interface like:
unsafe fn run_raw(
entrypoint: &[u8],
gp_args: &[u64],
fp_args: &[__m128]
) -> Result<UntypedRetVal, Error>;
This wouldn't be great to use for humans, but would be perfectly suitable for code generation.
Until WASI is open sourced by our pals at Mozilla, we're installing it in the devenv Dockerfile from moreproductive.org
(my own domain). Once the cranestation/wasi-sdk
repo is open sourced, we should point it at the release I tagged over there.
Currently, lucet-runtime uses dlopen
and dlsym
in the DlModule
struct to look up symbols in the lucetc-generated object file.
In order for static linking to work, we need to use lucet-module-data to access all aspects of a compiled module. This includes mapping export function names (as strings) to code pointers.
lucet-module-data will have to include a serialization of code pointers. Serde doesn't support this, so we'll have to serialize it directly with faerie and deserialize it with hand-written unsafe rust.
Hopefully, this same underlying representation will be usable by MockModule
, DlModule
, and StaticModule
, so that most of the difficult code lives in the Module trait, and the three different representations are as simple as possible.
Depends on #20
I tried the example from:
https://github.com/fastly/lucet/blob/master/lucet-runtime/src/lib.rs
use lucet_runtime::{DlModule, Limits, MmapRegion, Region};
fn main() {
let module = DlModule::load("hello.so").unwrap();
let region = MmapRegion::create(1, &Limits::default()).unwrap();
let mut inst = region
.new_instance_builder(module)
.build()
.unwrap();
inst.run(b"_start", &[]).unwrap();
}
However, I'm getting an error:
$ ./target/debug/lucet-example
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DlError(Custom { kind: Other, error: StringError("/stuff/lucet-example/hello.so: undefined symbol: lucet_vmctx_grow_memory") })', src/libcore/result.rs:997:5
I can run the module with lucet-wasi
$ ../lucet/target/release/lucet-wasi hello.so
Hello world!
After some poking around I managed to get this to work by adding lucet-example
crate to lucet
workspace.
Could you clarify why is this happening and what is a proper way to depend on lucet-runtime
?
This wat code:
(module
(import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
(import "wasi_unstable" "fd_read" (func $fd_read (param i32 i32 i32 i32) (result i32)))
(memory 10)
(export "memory" (memory 0))
;; prompt __wasi_ciovec_t struct
(data (i32.const 0) "\08\00\00\00") ;; buf: pointer to prompt string
(data (i32.const 4) "\02\00\00\00") ;; buf_len: 2 characters
;; string
(data (i32.const 8) "> ")
;; read buf __wasi_ciovec_t struct
(data (i32.const 16) "\18\00\00\00") ;; buf: pointer to string
(data (i32.const 20) "\64\00\00\00") ;; buf_len: 100 characters max
;; string
(data (i32.const 24) "\00") ;; buf (of 100 characters) to hold read in string
(func $main (local i32)
(loop $loop
(drop (call $fd_write (i32.const 1) (i32.const 0) (i32.const 1) (i32.const 256)))
(drop (call $fd_read (i32.const 0) (i32.const 16) (i32.const 1) (i32.const 256)))
(drop (call $fd_write (i32.const 0) (i32.const 16) (i32.const 1) (i32.const 256)))
(br $loop))
)
;;(start $main)
(export "_start" $main)
)
In wasmtime this works correctly reading and then printing what the user enters:
$ wasmtime wasitests/echo_loop.wasm
> foo
foo
> bar
bar
> ^C
In lucet, the first call to fd_read works, but each subsequent call immediately returns and the program loops rapidly printing the prompt:
# RUST_BACKTRACE=1 /opt/lucet/bin/lucet-wasi wasitests/echo_loop.so
> foo
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ...
In order to deprecate lucet-runtime-c, we need to create a C API that the existing users of lucet-runtime-c can migrate to. This interface doesn't need to be compatible with the lucet-runtime-c's.
@acfoltzer-fastly experimented with using https://github.com/eqrion/cbindgen for this, but it didn't pan out. We could either try another tool, or just maintain C bindings by hand.
heap doesn't grow.
int main(void) {
printf("%p\n", malloc(4 * 1024 * 1024)); // 4 MiB
return 0;
}
-> fails without lucetc --min-reserved-size 5MiB
or more
but max-reserved-size
is 4 GiB.
heap grows dynamically. Starts at min-reserved-size
, but can grow.
Functions like this are currently needed to force the C APIs to be exported. I opened this issue for Rust; when that's resolved, we should remove these functions.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.