https://docs.emilua.org/api/0.11/index.html
Emilua docs
Home Blog
Get the PDF
0.10 0.11 0.12 0.4 0.5 0.6 0.7 0.8 0.9
Get the EPUB
0.10 0.11 0.12 0.4 0.5 0.6 0.7 0.8 0.9
[ ] light
Emilua API 0.11
*
+ Conventions
+ ChangeLog
+ Tutorial
o Getting started
o Working with streams
o Filesystem API
o Alternative projects
o Internals
o Internals (sandboxes)
o Fiber cancellation API
o Lua 5.1
o Modules
o Errors
o Sandboxes
o Linux namespaces
o C++ embedder API
+ Reference
o generic_error
o asio_error
o format
o actor system
# inbox
# spawn_vm
# init.script
# spawn_context_threads
o byte_span
o filesystem
# path
# mode
# directory_entry
# directory_iterator
# recursive_directory_iterator
# absolute
# canonical
# weakly_canonical
# relative
# proximate
# current_working_directory
# chroot
# copy
# copy_file
# copy_symlink
# create_directory
# open
# mkdir
# create_hardlink
# create_symlink
# mkfifo
# mknod
# makedev
# dev_major
# dev_minor
# equivalent
# file_size
# hardlink_count
# clock
# last_write_time
# chown
# chmod
# read_symlink
# remove
# rename
# resize_file
# is_empty
# exists
# is_block_device
# is_character_device
# is_directory
# is_fifo
# is_other
# is_regular_file
# is_socket
# is_symlink
# space
# status
# temp_directory_path
# umask
# cap_get_file
# cap_set_file
o fiber
# spawn
# this_fiber
# mutex
# recursive_mutex
# condition_variable
# future
o file
# random_access
# stream
# read_all_at
# read_at_least_at
# write_all_at
# write_at_least_at
o ip
# address
# get_address_info
# get_name_info
# connect
# dial
# host_name
# tostring
# toendpoint
# tcp.listen
# tcp.acceptor
# tcp.socket
# udp.socket
o pipes
# read_stream
# write_stream
# pair
o regex
o serial_port
o time
# sleep
# steady_clock
# steady_timer
# system_clock
# system_timer
# high_resolution_clock
o stream
# write_all
# write_at_least
# read_all
# read_at_least
# scanner
o libc_service
# libc_service
# master
# slave
o system
# arguments
# environment
# in_
# out
# err
# caph_limit_stdio
# get_lowfd
# get_ld_library_directories
# exit
# signal
# signal.raise
# signal.set
# signal.ignore
# signal.default
# spawn
# Process credentials
@ getresuid
@ getresgid
@ setresuid
@ setresgid
@ getgroups
@ setgroups
@ set_no_new_privs
@ linux_capabilities
@ seccomp_set_mode_filter
@ landlock_create_ruleset
@ landlock_add_rule
@ landlock_restrict_self
# Process & job control
@ getpid
@ getppid
@ kill
@ getpgrp
@ getpgid
@ setpgid
@ getsid
@ setsid
# FreeBSD jails
@ jail_set
@ jail_get
@ jail_remove
@ jailparam_all
o tls
# dial
# context
# socket
o unix
# dial
# listen
# datagram.socket
# stream.acceptor
# stream.socket
# seqpacket.acceptor
# seqpacket.socket
o file_descriptor
Edit this Page Source Repository
* Emilua API
* Emilua
Emilua
emilua_overview
Emilua is an execution engine. As a runtime for your Lua programs,
it'll orchestrate concurrent systems by providing proper primitives
you can build upon.
emilua_simple
Emilua is not a framework. You don't design the structure of your
software by extending a complex concurrency framework. On the
contrary, you start simple and only makes use of primitives your
application needs. Should you only have the need for simple serial
programs, you'll have access to plenty of IO abstractions that work
across a broad range of platforms.
Fibers
emilua_simple
When your software grows and the need to increase the concurrency
level a notch arises, just spawn fibers. The same IO abstractions
that work on serial programs will work on concurrent programs as
well. You don't need to pay an extra huge cost by completely
refactoring your program during this transition^[1].
Sandboxes
emilua_simple
Emilua has first-class support for modern sandboxing technologies.
* Linux.
+ Namespaces.
+ Seccomp.
+ Landlock.
* FreeBSD.
+ Jails.
+ Capsicum.
Mitigate risks by creating disposable cheap sandboxes to parse
untrusted input data.
Sandboxing support on Emilua is based around capabilities and
elegantly integrates with the same machinery that is used to
implement the actor model.
Compartmentalised application development is, of necessity,
distributed application development, with software components
running in different processes and communicating via message
passing.
-- Capsicum: practical capabilities for UNIX
Robert N. M. Watson, Jonathan Anderson, Ben Laurie, and Kris Kennaway
The only resource a sandbox starts with is inbox and its only method:
receive(). In this initial state, a sandbox can't even ask for new
resources (i.e. it's a push model). The Lua VM on the host system can
then selectively choose which resources are safe to hand over (e.g.
read-only access to a file and a pipe).
There's also an optional compatibility layer that interposes key
functions^[2] from libc to translate such calls as requests to a
supervisor so it becomes possible to use existing code within
sandboxes w/o the need to rewrite them to work on tightly sandboxed
environments. With some extra work it's even possible to use this
layer to offer something closer to Capsicum within Linux. A
standalone library that you can LD_PRELOAD into other executables
also exists so you can use this layer even for applications that have
nothing to do with Emilua.
Container runtime
A generic C-powered & Lua-driven container runtime. Many container
runtimes out there focus on specific containerization technologies
such as Linux namespaces, but Emilua acts as a generic container
runtime that supports different kernel technologies^[3]:
* Linux namespaces.
* FreeBSD jails.
Many container runtimes (e.g. bubblewrap, nsjail) are CLI-driven and
give little room for flexibility. The standard tool to automate CLI
usage is BASH. However BASH cannot be used to restore flexibility
here (it can only automate CLI arguments). BASH scripts are a poor
match for the internal container setup phases, and that's not usually
supported. Even when BASH is supported for the setup phases (e.g. LXC
pre-mount, and net-up scripts), that's usually very restricted in
scope given how inappropriate BASH is to drive the setup phases of a
container. BASH scripts give you more worries to bring up a
container, not less:
* Poor synchronization primitives to drive the complex setup
required to use new Linux namespaces. BASH only gives you pipes
and files. Files can't even be used in all steps of this setup
(e.g. mount namespaces and pivot-root). Emilua will give you a
rich pool of IPC primitives not available to BASH scripts (check
the documentation).
* You must be extra careful to not call any binaries from the
container image as one must always assume these images are
compromised (that's the whole point of isolating software within
a container to begin with), but BASH can't do anything on its own
and must always rely on external tools (it's probably a good idea
to rely on static binaries of busybox as well to not accidentally
invoke compromised shared libraries from the container image).
Emilua is safer as it gives you access to a subset of the POSIX
API plus a few extensions (e.g. mkdir, mount) that calls the
syscalls directly (i.e. no container binaries ever involved)
within a Lua script to initialize the container namespaces.
The pragmatic solution is to never involve BASH in the setup of Linux
namespaces. The CLI tool would do all actions declared in the initial
arguments on your behalf, and only return you the final result. The
downside is a big loss in flexibility. If your use case falls outside
of the tool's envisioned cases, you're out of options.
Emilua is designed differently. Emilua offers you a fully-featured
programming language and VM -- that's Lua -- to script the setup phases
inside the containerized process.
However any general-purpose programming language can escape from
BASH's shortcomings with respect to containerization challenges. Any
container runtime meant to be used from source code -- not a CLI
tool -- will be flexible enough to more use cases. The new challenge
here is how to avoid leaking resources from the language's own
runtime to the container. That's why it's easy to create a container
runtime using C, but not so much for Java or Python.
What Emilua gives to Lua is a container runtime that surpassed these
challenges and is ready to roll. The API provides two contexts
(program and container initialization), and you can coordinate both
to initialize your container programmatically any way you want. The
container initialization context was paranoiacally implemented to not
inherit the parent process's sensitive context (e.g. memory other
than the executable itself, env vars), to abort on any C API error by
default, and to securely erase the contents of temporary buffers
(e.g. messages received through C.read() within the initialization
script, and any memory allocated by the Lua VM). You won't find any
of these in other Lua projects.
A note on FreeBSD jails
FreeBSD jails work differently than Linux namespaces, and complex
setups are not really needed. However Emilua can still offer a few
goodies here such as attaching to an existing jail using a clean
OS-level process to perform container-side administrative tasks not
specified by binaries found on the container image.
Later -- should you desire -- you can still use BASH to orchestrate
Emilua programs after the setup phases are fully encapsulated just
inside Emilua programs. If you have no needs for customizing the
container setup phases, then Emilua doesn't bring any advantages over
other tools -- bubblewrap, nsjail, etc -- and you're already well
served with the existing market solutions.
The same machinery used for containers is also used to create
capsicum sandboxes. That's a testament of the runtime's flexibility.
Capsicum pose API requirements that cannot be met if you can only
think and design in terms of the seccomp model. Emilua is the only
container runtime also able to drive full use of capsicum sandboxes.
Cross-platform
* Windows.
* Linux.
* FreeBSD.
Emilua is powered by the battle-tested and scar-accumulating
Boost.Asio library to drive IO and it'll make use of native APIs in a
long list of supported platforms. However processor ISA compatibility
will be limited by LuaJIT availability.
Network IO
* TCP.
* UDP.
* TLS.
* Address/service forward/reverse name resolution.
* IPv6 support (and mostly transparent).
* Cancellable operations transparently integrated into the fiber
cancellation API.
* Several generic algorithms.
IPC
* UNIX domain sockets (stream, datagram, and seqpacket).
* SCM_RIGHTS fd-passing.
* Pipes.
* UNIX signals.
* Ctty job control (and basic pty support).
Filesystem API
* It easily abstracts path manipulation for different platforms
(e.g. POSIX & Windows).
* Transparently translates to UTF-8 while retaining the native
representation for the underlying system under the hood.
* Directory iterators (flat and recursive).
* APIs to query attributes, manipulate permissions, and the like.
* Lots of algorithms (e.g. symlink-resolving path canonization,
subtrees copying, etc).
Misc features
* Complete fiber API (sync primitives, cancellation API, clean-up
handlers, fiber local storage, assert-like scheduling
constraints, ... ).
* Integrates with Lua builtins (i.e. you can mix up fibers and
coroutines, modules, ... ).
* AWK-inspired scanner to parse textual streams easily.
* Clocks & timers.
* File IO (for proactors only^[4], so the main thread never
blocks).
* Serial ports.
* A basic regex module.
* Portable error code comparison.
* And much more.
---------------------------------------------------------------------
1. Emilua doesn't suffer from Bob Nystrom' two colors problem.
2. Mostly related to ambient authority.
3. Future releases will also implement virtio-vsock to ease
communication with containers managed by QEMU
4. Right now, Windows' IOCP, and Linux's io_uring.
Conventions