Nuxi

Nuxi CloudABI

CloudABI is what you get if you take POSIX, add capability-based security, and remove everything that's incompatible with that. The result is a minimal ABI consisting of only 49 syscalls.

CloudABI doesn't have its own kernel, but instead is implemented in existing kernels: FreeBSD has CloudABI support for x86-64 and arm64, and a patch-set for NetBSD and a patch-set for Linux are available as well. This means that CloudABI binaries can be executed on different operating systems, without any modification.

Capability-Based Security

Capability-based security means that processes can only perform actions that have no global impact. Processes cannot open files by their absolute path, cannot open network connections, and cannot observe global system state such as the process table.

The capabilities of a process are fully determined by its set of open file descriptors (fds). For example, files can only be opened if the process already has a file descriptor to a directory the file is in.

Unlike in POSIX, where processes are normally started with file descriptors 0, 1, and 2 reserved for standard input, output, and error, CloudABI does not reserve any file descriptor numbers for specific purposes.

In CloudABI, a process depends on its parent process to launch it with the right set of resources, since the process will not be able to open any new resources. For example, a simple static web server would need to be started with a file descriptor to a TCP listener, and a file descriptor to the directory for which to serve files. The web server will then be unable to do anything other than reading files in that directory, and process incoming network connections.

So, unknown CloudABI binaries can safely be executed without the need for containers, virtual machines, or other sandboxing technologies.

Watch Ed Schouten's Talk at 32C3 for more information about what capability-based security for UNIX means.

Cloudlibc

Cloudlibc is an implementation of the C standard library, without all CloudABI-incompatible functions. For example, Cloudlibc does not have printf, but does have fprintf. It does not have open, but does have openat.

CloudABI-Ports

CloudABI-Ports is a collection of ports of commonly used libraries and applications to CloudABI. It contains software such as zlib, libpng, boost, memcached, and much more. The software is patched to not depend on any global state, such as files in /etc or /dev, using open(), etc.

Using CloudABI

Instructions for using CloudABI (including kernel modules/patches, toolchain, and ports) are available for several operating systems:

Specification of the ABI

The entire ABI is specified in a a file called cloudabi.txt, from which all headers and documentation (including the one you're reading now) is generated.

System calls

cloudabi_sys_clock_res_get()

Obtains the resolution of a clock.

Inputs:

Outputs:

cloudabi_sys_clock_time_get()

Obtains the time value of a clock.

Inputs:

Outputs:

cloudabi_sys_condvar_signal()

Wakes up threads waiting on a userspace condition variable.

If an invocation of this system call causes all waiting threads to be woken up, the value of the condition variable is set to CLOUDABI_CONDVAR_HAS_NO_WAITERS. As long as the condition variable is set to this value, it is not needed to invoke this system call.

Inputs:

cloudabi_sys_fd_close()

Closes a file descriptor.

Inputs:

cloudabi_sys_fd_create1()

Creates a file descriptor.

Inputs:

Outputs:

cloudabi_sys_fd_create2()

Creates a pair of file descriptors.

Inputs:

Outputs:

cloudabi_sys_fd_datasync()

Synchronizes the data of a file to disk.

Inputs:

cloudabi_sys_fd_dup()

Duplicates a file descriptor.

Inputs:

Outputs:

cloudabi_sys_fd_pread()

Reads from a file descriptor, without using and updating the file descriptor's offset.

Inputs:

Outputs:

cloudabi_sys_fd_pwrite()

Writes to a file descriptor, without using and updating the file descriptor's offset.

Inputs:

Outputs:

cloudabi_sys_fd_read()

Reads from a file descriptor.

Inputs:

Outputs:

cloudabi_sys_fd_replace()

Atomically replaces a file descriptor by a copy of another file descriptor.

Due to the strong focus on thread safety, this environment does not provide a mechanism to duplicate a file descriptor to an arbitrary number, like dup2(). This would be prone to race conditions, as an actual file descriptor with the same number could be allocated by a different thread at the same time.

This system call provides a way to atomically replace file descriptors, which would disappear if dup2() were to be removed entirely.

Inputs:

cloudabi_sys_fd_seek()

Moves the offset of the file descriptor.

Inputs:

Outputs:

cloudabi_sys_fd_stat_get()

Gets attributes of a file descriptor.

Inputs:

cloudabi_sys_fd_stat_put()

Adjusts attributes of a file descriptor.

Inputs:

cloudabi_sys_fd_sync()

Synchronizes the data and metadata of a file to disk.

Inputs:

cloudabi_sys_fd_write()

Writes to a file descriptor.

Inputs:

Outputs:

cloudabi_sys_file_advise()

Provides file advisory information on a file descriptor.

Inputs:

cloudabi_sys_file_allocate()

Forces the allocation of space in a file.

Inputs:

cloudabi_sys_file_create()

Creates a file of a specified type.

Inputs:

cloudabi_sys_file_link()

Creates a hard link.

Inputs:

cloudabi_sys_file_open()

Opens a file.

Inputs:

Outputs:

cloudabi_sys_file_readdir()

Reads directory entries from a directory.

When successful, the contents of the output buffer consist of a sequence of directory entries. Each directory entry consists of a cloudabi_dirent_t object, followed by cloudabi_dirent_t::d_namlen bytes holding the name of the directory entry.

This system call fills the output buffer as much as possible, potentially truncating the last directory entry. This allows the caller to grow its read buffer size in case it's too small to fit a single large directory entry, or skip the oversized directory entry.

Inputs:

Outputs:

cloudabi_sys_file_readlink()

Reads the contents of a symbolic link.

Inputs:

Outputs:

cloudabi_sys_file_rename()

Renames a file.

Inputs:

cloudabi_sys_file_stat_fget()

Gets attributes of a file by file descriptor.

Inputs:

cloudabi_sys_file_stat_fput()

Adjusts attributes of a file by file descriptor.

Inputs:

cloudabi_sys_file_stat_get()

Gets attributes of a file by path.

Inputs:

cloudabi_sys_file_stat_put()

Adjusts attributes of a file by path.

Inputs:

cloudabi_sys_file_symlink()

Creates a symbolic link.

Inputs:

cloudabi_sys_file_unlink()

Unlinks a file, or removes a directory.

Inputs:

cloudabi_sys_lock_unlock()

Unlocks a write-locked userspace lock.

If a userspace lock is unlocked while having its CLOUDABI_LOCK_KERNEL_MANAGED flag set, the lock cannot be unlocked in userspace directly. This system call needs to be performed instead, so that any waiting threads can be woken up.

To prevent spurious invocations of this system call, the lock must be locked for writing. This prevents other threads from acquiring additional read locks while the system call is in progress. If the lock is acquired for reading, it must first be upgraded to a write lock.

Inputs:

cloudabi_sys_mem_advise()

Provides memory advisory information on a region of memory.

Inputs:

cloudabi_sys_mem_map()

Creates a memory mapping, making the contents of a file accessible through memory.

Inputs:

Outputs:

cloudabi_sys_mem_protect()

Change the protection of a memory mapping.

Inputs:

cloudabi_sys_mem_sync()

Synchronize a region of memory with its physical storage.

Inputs:

cloudabi_sys_mem_unmap()

Unmaps a region of memory.

Inputs:

cloudabi_sys_poll()

Concurrently polls for the occurrence of a set of events.

Inputs:

Outputs:

cloudabi_sys_proc_exec()

Replaces the process by a new executable.

Process execution in CloudABI differs from POSIX in two ways: handling of arguments and inheritance of file descriptors.

CloudABI does not use string command line arguments. Instead, a buffer with binary data is copied into the address space of the new executable. The kernel does not enforce any specific structure to this data, although CloudABI's C library uses it to store a tree structure that is semantically identical to YAML.

Due to the strong focus on thread safety, file descriptors aren't inherited through close-on-exec flags. An explicit list of file descriptors that need to be retained needs to be provided. After execution, file descriptors are placed in the order in which they are stored in the array. This not only makes the execution process deterministic. It also prevents potential information disclosures about the layout of the original process.

Inputs:

cloudabi_sys_proc_exit()

Terminates the process normally.

Inputs:

Does not return.

cloudabi_sys_proc_fork()

Forks the process of the calling thread.

After forking, a new process shall be created, having only a copy of the calling thread. The parent process will obtain a process descriptor. When closed, the child process is automatically signaled with CLOUDABI_SIGKILL.

Outputs:

cloudabi_sys_proc_raise()

Sends a signal to the process of the calling thread.

Inputs:

cloudabi_sys_random_get()

Obtains random data from the kernel random number generator.

As this interface is not guaranteed to be fast, it is advised that the random data obtained through this system call is used as the seed for a userspace pseudo-random number generator.

Inputs:

cloudabi_sys_sock_recv()

Receives a message on a socket.

Inputs:

cloudabi_sys_sock_send()

Sends a message on a socket.

Inputs:

cloudabi_sys_sock_shutdown()

Shuts down socket send and receive channels.

Inputs:

cloudabi_sys_thread_create()

Creates a new thread within the current process.

Inputs:

Outputs:

cloudabi_sys_thread_exit()

Terminates the calling thread.

This system call can also unlock a single userspace lock after termination, which can be used to implement thread joining.

Inputs:

Does not return.

cloudabi_sys_thread_yield()

Temporarily yields execution of the calling thread.

Types

cloudabi_advice_t (uint8_t)

File or memory access pattern advisory information.

Used by cloudabi_sys_file_advise() and cloudabi_sys_mem_advise().

Possible values:

cloudabi_auxtype_t (uint32_t)

Enumeration describing the kind of value stored in cloudabi_auxv_t.

Possible values:

cloudabi_auxv_t (struct)

Auxiliary vector entry.

The auxiliary vector is a list of key-value pairs that is provided to the process on startup. Unlike structures, it is extensible, as it is possible to add new records later on. The auxiliary vector is always terminated by an entry having type CLOUDABI_AT_NULL.

The auxiliary vector is part of the x86-64 ABI, but is used by this environment on all architectures.

Used by cloudabi_processentry_t.

Members:

cloudabi_ciovec_t (struct)

A region of memory for scatter/gather writes.

Used by cloudabi_send_in_t, cloudabi_sys_fd_pwrite(), and cloudabi_sys_fd_write().

Members:

cloudabi_clockid_t (uint32_t)

Identifiers for clocks.

Used by cloudabi_subscription_t, cloudabi_sys_clock_res_get(), and cloudabi_sys_clock_time_get().

Possible values:

cloudabi_condvar_t (uint32_t)

A userspace condition variable.

Used by cloudabi_event_t, cloudabi_subscription_t, and cloudabi_sys_condvar_signal().

Special values:

cloudabi_device_t (uint64_t)

Identifier for a device containing a file system. Can be used in combination with cloudabi_inode_t to uniquely identify a file on the local system.

Used by cloudabi_filestat_t.

cloudabi_dircookie_t (uint64_t)

A reference to the offset of a directory entry.

Used by cloudabi_dirent_t and cloudabi_sys_file_readdir().

Special values:

cloudabi_dirent_t (struct)

A directory entry.

Members:

cloudabi_errno_t (uint16_t)

Error codes returned by system calls.

Not all of these error codes are returned by the system calls provided by this environment, but are either used in userspace exclusively or merely provided for alignment with POSIX.

Used by cloudabi_event_t.

Possible values:

cloudabi_event_t (struct)

An event that occurred.

Used by cloudabi_sys_poll().

Members:

cloudabi_eventrwflags_t (uint16_t bitfield)

The state of the file descriptor subscribed to with CLOUDABI_EVENTTYPE_FD_READ or CLOUDABI_EVENTTYPE_FD_WRITE.

Used by cloudabi_event_t.

Possible values:

cloudabi_eventtype_t (uint8_t)

Type of a subscription to an event or its occurrence.

Used by cloudabi_event_t and cloudabi_subscription_t.

Possible values:

cloudabi_exitcode_t (uint32_t)

Exit code generated by a process when exiting.

Used by cloudabi_event_t and cloudabi_sys_proc_exit().

cloudabi_fd_t (uint32_t)

A file descriptor number.

Unlike on POSIX-compliant systems, none of the file descriptor numbers are reserved for a purpose (e.g., stdin, stdout, stderr). Operating systems are not required to allocate new file descriptors in ascending order.

Special values:

cloudabi_fdflags_t (uint16_t bitfield)

File descriptor flags.

Used by cloudabi_fdstat_t.

Possible values:

cloudabi_fdsflags_t (uint16_t bitfield)

Which file descriptor attributes to adjust.

Used by cloudabi_sys_fd_stat_put().

Possible values:

cloudabi_fdstat_t (struct)

File descriptor attributes.

Used by cloudabi_sys_fd_stat_get(), cloudabi_sys_fd_stat_put(), and cloudabi_sys_file_open().

Members:

cloudabi_filedelta_t (int64_t)

Relative offset within a file.

Used by cloudabi_sys_fd_seek().

cloudabi_filesize_t (uint64_t)

Non-negative file size or length of a region within a file.

Used by cloudabi_event_t, cloudabi_filestat_t, cloudabi_sys_fd_pread(), cloudabi_sys_fd_pwrite(), cloudabi_sys_fd_seek(), cloudabi_sys_file_advise(), cloudabi_sys_file_allocate(), and cloudabi_sys_mem_map().

cloudabi_filestat_t (struct)

File attributes.

Used by cloudabi_sys_file_stat_fget(), cloudabi_sys_file_stat_fput(), cloudabi_sys_file_stat_get(), and cloudabi_sys_file_stat_put().

Members:

cloudabi_filetype_t (uint8_t)

The type of a file descriptor or file.

Used by cloudabi_dirent_t, cloudabi_fdstat_t, cloudabi_filestat_t, cloudabi_sys_fd_create1(), cloudabi_sys_fd_create2(), and cloudabi_sys_file_create().

Possible values:

cloudabi_fsflags_t (uint16_t bitfield)

Which file attributes to adjust.

Used by cloudabi_sys_file_stat_fput() and cloudabi_sys_file_stat_put().

Possible values:

cloudabi_inode_t (uint64_t)

File serial number that is unique within its file system.

Used by cloudabi_dirent_t and cloudabi_filestat_t.

cloudabi_iovec_t (struct)

A region of memory for scatter/gather reads.

Used by cloudabi_recv_in_t, cloudabi_sys_fd_pread(), and cloudabi_sys_fd_read().

Members:

cloudabi_linkcount_t (uint32_t)

Number of hard links to an inode.

Used by cloudabi_filestat_t.

cloudabi_lock_t (uint32_t)

A userspace read-recursive readers-writer lock, similar to a Linux futex or a FreeBSD umtx.

Used by cloudabi_event_t, cloudabi_subscription_t, cloudabi_sys_lock_unlock(), and cloudabi_sys_thread_exit().

Special values:

cloudabi_lookup_t (struct)

Path lookup properties.

Used by cloudabi_sys_file_link(), cloudabi_sys_file_open(), cloudabi_sys_file_stat_get(), and cloudabi_sys_file_stat_put().

Members:

cloudabi_lookupflags_t (uint32_t bitfield)

Flags determining the method of how paths are resolved.

Used by cloudabi_lookup_t.

Possible values:

cloudabi_mflags_t (uint8_t bitfield)

Memory mapping flags.

Used by cloudabi_sys_mem_map().

Possible values:

cloudabi_mprot_t (uint8_t bitfield)

Memory page protection options.

This implementation enforces the W^X property: Pages cannot be mapped for execution while also mapped for writing.

Used by cloudabi_sys_mem_map() and cloudabi_sys_mem_protect().

Possible values:

cloudabi_msflags_t (uint8_t bitfield)

Methods of synchronizing memory with physical storage.

Used by cloudabi_sys_mem_sync().

Possible values:

cloudabi_nthreads_t (uint32_t)

Specifies the number of threads sleeping on a condition variable that should be woken up.

Used by cloudabi_sys_condvar_signal().

cloudabi_oflags_t (uint16_t bitfield)

Open flags used by cloudabi_sys_file_open().

Possible values:

cloudabi_processentry_t (function type)

Entry point for a process (_start).

Parameters:

cloudabi_recv_in_t (struct)

Arguments of cloudabi_sys_sock_recv().

Members:

cloudabi_recv_out_t (struct)

Results of cloudabi_sys_sock_recv().

Members:

cloudabi_riflags_t (uint16_t bitfield)

Flags provided to cloudabi_sys_sock_recv().

Used by cloudabi_recv_in_t.

Possible values:

cloudabi_rights_t (uint64_t bitfield)

File descriptor rights, determining which actions may be performed.

Used by cloudabi_fdstat_t.

Possible values:

cloudabi_roflags_t (uint16_t bitfield)

Flags returned by cloudabi_sys_sock_recv().

Used by cloudabi_recv_out_t.

Possible values:

cloudabi_scope_t (uint8_t)

Indicates whether an object is stored in private or shared memory.

Used by cloudabi_subscription_t, cloudabi_sys_condvar_signal(), cloudabi_sys_lock_unlock(), and cloudabi_sys_thread_exit().

Possible values:

cloudabi_sdflags_t (uint8_t bitfield)

Which channels on a socket need to be shut down.

Used by cloudabi_sys_sock_shutdown().

Possible values:

cloudabi_send_in_t (struct)

Arguments of cloudabi_sys_sock_send().

Members:

cloudabi_send_out_t (struct)

Results of cloudabi_sys_sock_send().

Members:

cloudabi_siflags_t (uint16_t bitfield)

Flags provided to cloudabi_sys_sock_send(). As there are currently no flags defined, it must be set to zero.

Used by cloudabi_send_in_t.

cloudabi_signal_t (uint8_t)

Signal condition.

Used by cloudabi_event_t and cloudabi_sys_proc_raise().

Possible values:

cloudabi_subclockflags_t (uint16_t bitfield)

Flags determining how the timestamp provided in cloudabi_subscription_t::clock.timeout should be interpreted.

Used by cloudabi_subscription_t.

Possible values:

cloudabi_subrwflags_t (uint16_t bitfield)

Flags influencing the method of polling for read or writing on a file descriptor.

Used by cloudabi_subscription_t.

Possible values:

cloudabi_subscription_t (struct)

Subscription to an event.

Used by cloudabi_sys_poll().

Members:

cloudabi_tcb_t (struct)

The Thread Control Block (TCB).

After a thread begins execution (at program startup or when created through cloudabi_sys_thread_create()), the CPU's registers controlling Thread-Local Storage (TLS) will already be initialized. They will point to an area only containing the TCB.

If the thread needs space for storing thread-specific variables, the thread may allocate a larger area and adjust the CPU's registers to point to that area instead. However, it does need to make sure that the TCB is copied over to the new TLS area.

The purpose of the TCB is that it allows light-weight emulators to store information related to individual threads. For example, it may be used to store a copy of the CPU registers prior emulation, so that TLS for the host system can be restored if needed.

Members:

cloudabi_threadattr_t (struct)

Attributes for thread creation.

Used by cloudabi_sys_thread_create().

Members:

cloudabi_threadentry_t (function type)

Entry point for additionally created threads.

Used by cloudabi_threadattr_t.

Parameters:

cloudabi_tid_t (uint32_t)

Unique system-local identifier of a thread. This identifier is only valid during the lifetime of the thread.

Threads must be aware of their thread identifier, as it is written it into locks when acquiring them for writing. It is not advised to use these identifiers for any other purpose.

As the thread identifier is also stored in cloudabi_lock_t when CLOUDABI_LOCK_WRLOCKED is set, the top two bits of the thread must always be set to zero.

Used by cloudabi_threadentry_t, cloudabi_sys_proc_fork(), and cloudabi_sys_thread_create().

cloudabi_timestamp_t (uint64_t)

Timestamp in nanoseconds.

Used by cloudabi_filestat_t, cloudabi_subscription_t, cloudabi_sys_clock_res_get(), and cloudabi_sys_clock_time_get().

cloudabi_ulflags_t (uint8_t bitfield)

Specifies whether files are unlinked or directories are removed.

Used by cloudabi_sys_file_unlink().

Possible values:

cloudabi_userdata_t (uint64_t)

User-provided value that can be attached to objects that is retained when extracted from the kernel.

Used by cloudabi_event_t and cloudabi_subscription_t.

cloudabi_whence_t (uint8_t)

Relative to which position the offset of the file descriptor should be set.

Used by cloudabi_sys_fd_seek().

Possible values: