Skip to content

Commit 19f4952

Browse files
authored
Merge pull request #1 from rust-osdev/rusty-hermit-showcase-improvements
Various improvements for RustyHermit showcase post
2 parents 2bcc306 + adc9a2a commit 19f4952

File tree

4 files changed

+58
-38
lines changed

4 files changed

+58
-38
lines changed

content/showcase/rusty-hermit.md renamed to content/showcase/rusty-hermit/index.md

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,73 +6,93 @@ date = 2021-01-17
66
authors = ["stlankes"]
77
+++
88

9-
[RustyHermit](https://github.com/hermitcore/rusty-hermit) is a unikernel, which is completely written Rust. [Unikernel](http://unikernel.org/) are application images that directly contain the kernel as a library, so it does not require an installed operating system (OS). They are typical used in virtualized environments, which build the backbone of typical cloud / edge infrastructures.
9+
[RustyHermit](https://github.com/hermitcore/rusty-hermit) is a unikernel, which is completely written Rust. [Unikernels](http://unikernel.org/) are application images that directly contain the kernel as a library, so they do not require an installed operating system (OS). They are typical used in virtualized environments, which build the backbone of typical cloud / edge infrastructures.
1010

11-
Common virtualized environment based on classical virtual machines. In this case, complete machines are emulated or virtualized and on host and guest site are running common operating systems. This technique is established (VMware, Hyper-V, etc.) and widely used. However, it introduces additional overhead especially regarding memory consumption and performance.
11+
## Virtualization Designs
1212

13-
![Structure of a common virtualitation environment](../common_vm.png)
13+
Common virtualized environment based on classical **_virtual machines_**. In this case, complete machines are emulated or virtualized and common operating systems are running on both host and guest site:
1414

15-
An alternative approach to common virtual machines is OS-level
16-
virtualization, where the kernel allows the existence of multiple
15+
![Structure of a common virtualitation environment](common_vm.png)
16+
17+
This technique is established (VMware, Hyper-V, etc.) and widely used. However, it introduces additional overhead especially regarding memory consumption and performance.
18+
19+
An alternative approach to common virtual machines is **OS-level
20+
virtualization**, where the kernel allows the existence of multiple
1721
isolated user space instances. These isolated instances are also known
1822
as container. A typical representative is LXC or Docker and promise less
1923
overhead in comparison to common virtual machines. However, the
2024
isolation between the processes is weaker and may provide less security.
2125

22-
Often only one application (e.g. a web server) is running in the container or the virtual machine. In this case, is a unikernel an attractive solution. The kernel is provided as static library and linked to the application. As the images directly contain the OS kernel, unikernels can directly be bootet inside a virtual machine and do not require the typical software stack containing a linux kernel and its userland within the VM.
26+
## Unikernels
27+
28+
Often only one application (e.g. a web server) is running in the container or the virtual machine. In this case, a _unikernel_ is an attractive solution. The kernel is provided as static library and linked to the application. As the images directly contain the OS kernel, unikernels can directly be booted inside a virtual machine and do not require the typical software stack containing a Linux kernel and its userland within the VM.
2329

24-
Unikernels do not provide system calls in the classical sense, as everything is running with the privilege level of a kernel and what is typically done via system calls is provided via a common function call. At first glance, this sounds more insecure than previous approaches. However, these kernels are expected to run within a virtual machine, which isolated the application from the real system. In addition, common compiler analysis is used to check the complete software stack and even unneeded components can be removed, which can reduce the attack surface of the application.
30+
Unikernels do not provide system calls in the classical sense, as everything is running with the privilege level of a kernel and what is typically done via system calls is provided via a common function call. At first glance, this sounds more insecure than previous approaches. However, these kernels are expected to run within a virtual machine, which isolates the application from the real system. In addition, common compiler analysis is used to check the complete software stack and unneeded components can even be removed, which can reduce the attack surface of the application.
2531

26-
![Structure of a library operating system](../libos.png)
32+
![Structure of a library operating system](libos.png)
2733

2834
Well known unikernels are kernels such as [MirageOS](https://mirage.io/)
2935
and [Unikraft](http://www.unikraft.org/). MirageOS is written in OCaml,
30-
while Unikraft still use C as programming language. In contrast to these
36+
while Unikraft still uses C as programming language. In contrast to these
3137
kernels, RustyHermit is completely written in Rust to benefit from
32-
Rust's performance and security behavior. In principle, every existing
38+
Rust's performance and security behavior.
39+
40+
## RustyHermit
41+
42+
In principle, every existing
3343
Rust application can be built on top of RustyHermit. However, unikernels
3444
are a single tasking operating system. Consequently, the support of the
3545
system call `fork` and inter-process communication are missing. In
3646
addition, a classical C library is missing, which is typical used as
37-
interface to the operating system. Every crate, which bypass the
47+
interface to the operating system. Every crate, which bypasses the
3848
standard runtime and tries to communicate directly to operating system
3949
does not work without modifications. However, many applications do not
4050
depend on these features and work on RustyHermit.
4151

52+
### Performance
53+
4254
Unikernels can be highly optimized. For instance, we optimized the
4355
network stack of RustyHermit. RustyHermit uses
4456
[smoltcp](https://github.com/smoltcp-rs/smoltcp) as network stack, which
4557
is completely written in Rust. As interface between guest and host
4658
operating system, we use
4759
[Virtio](https://www.linux-kvm.org/page/Virtio), which is in a
4860
para-virtualized driver for KVM and widely used in virtualized Linux
49-
environments. The following figure compares Linux with RustyHermit,
61+
environments.
62+
63+
The following figure compares Linux with RustyHermit,
5064
where both are running as guests inside a virtual machine running on top
51-
of a Linux-based host system. Especially for small messages RustHermit
65+
of a Linux-based host system:
66+
67+
![Bandwidth of the RustyHermit's exerimental network interface](bandwidth.png)
68+
69+
Especially for small messages RustHermit
5270
is faster in than Linux.
5371

54-
![Bandwidth of the RustyHermit's exerimental network interface](../bandwidth.png)
72+
### Research
5573

5674
RustyHermit is also a research project to evaluate new operating
57-
systems designs, which improves the scalability and the security of operating systems in cloud environments. For instance, RustyHermit provides classical
75+
system designs, which improves the scalability and the security of operating systems in cloud environments. For instance, RustyHermit provides classical
5876
techniques to improve the security behavior like stack guards and
59-
separating the application stack from the libos stack. However, a
60-
library operating system uses typical a common function call to enter
61-
the kernel. A classical separation from user- and kernel space by
77+
separating the application stack from the libOS stack. However, a
78+
library operating system typically uses a common function call to enter
79+
the kernel. A classical separation of user- and kernel space by
6280
entering a higher privilege level is missing. We presented in a
63-
[paper](https://www.ssrg.ece.vt.edu/papers/vee20-mpk.pdf) a modified
64-
version of RustyHermit, which provides an intra-unikernel isolation with
65-
Intel Memory Protection Keys (MPK). MPK is a relatively new hard-ware
66-
primitive that provides per-thread permission control over groups of
67-
pages in a single address space with [negligible switching overhead](https://www.usenix.org/conference/atc19/presentation/park-soyeon),
68-
making it a compelling candidate for use in unikernels.
81+
[paper](https://www.ssrg.ece.vt.edu/papers/vee20-mpk.pdf) a modified
82+
version of RustyHermit, which provides an intra-unikernel isolation with
83+
_Intel Memory Protection Keys_ (MPK). MPK is a relatively new hard-ware
84+
primitive that provides per-thread permission control over groups of
85+
pages in a single address space with [negligible switching overhead](https://www.usenix.org/conference/atc19/presentation/park-soyeon),
86+
making it a compelling candidate for use in unikernels.
6987

70-
MPK is requiring modification of page tables at a small performance cost. Four previously-unused bits of each page table entry (the 62nd to the 59th on x86-64) are exploited by MPK. Since MPK exploits four bits of the page table entry, it supports up to 15 protection keys.
71-
MPK controls per-thread permission on groups of pages. Each core has a PKRU register (32 bits) containing a permission value. The value of the PKRU register defines the permission of the thread currently running on that core for each group of pages containing a protection key in their page table entries. Unlike page-table-level permission, MPK provides thread-local memory permission.
88+
MPK is requiring modification of page tables at a small performance cost. Four previously-unused bits of each page table entry (the 62nd to the 59th on x86-64) are exploited by MPK. Since MPK exploits four bits of the page table entry, it supports up to 15 protection keys.
89+
MPK controls per-thread permission on groups of pages. Each core has a PKRU register (32 bits) containing a permission value. The value of the PKRU register defines the permission of the thread currently running on that core for each group of pages containing a protection key in their page table entries. Unlike page-table-level permission, MPK provides thread-local memory permission.
7290

7391
We provide user / kernel separation so we simply see the entire application as an untrusted component, independently of application-specific characteristics such as the language it is written in or the level of skill of the application’s programmer. In addition, we divide the kernel code into trusted and untrusted components. Trusted kernel components represent pieces of code written with a memory-safe language, i.e., offering strong security guarantees. Untrusted kernel components correspond to code written either in memory-unsafe languages or in unsafe Rust code blocks.
7492

75-
By entering the library operating system through the application binary interface, the protection keys will be automatically changed and allows access to the kernel stack and the kernel heap. Unauthorized access from within the application will trigger a pagefault, which will be handled by the library operating system.
93+
By entering the library operating system through the application binary interface the protection keys will be automatically changed, which allows access to the kernel stack and the kernel heap. Unauthorized access from within the application will trigger a pagefault, which will be handled by the library operating system.
94+
95+
### Example Project
7696

7797
To give you an example on how to build an RustyHermit application, lets create a new cargo project:
7898

@@ -84,11 +104,9 @@ cd hello_world
84104
RustyHermit currently requires the nightly versions of the Rust toolchain.
85105
To simplify the workflow, we recommend to create the configuration
86106
_rust-toolchain_ as follows to define the required components and to
87-
tested version of nightly compiler.
88-
89-
To simplify the workflow, we recommend that you create the _rust-toolchain_ configuration file as follows:
107+
tested version of nightly compiler:
90108

91-
```
109+
```toml
92110
[toolchain]
93111
channel = "nightly-2020-12-23"
94112
components = [ "rustfmt", "rust-src", "llvm-tools-preview"]
@@ -104,15 +122,15 @@ standard runtime must be build from scratch.
104122
To simplify this build process, we recommend to create the configuration
105123
file `.cargo/config` as follows:
106124

107-
```
125+
```toml
108126
[unstable]
109127
build-std = ["std", "core", "alloc", "panic_abort"]
110128

111129
[build]
112130
target = "x86_64-unknown-hermit"
113-
``
131+
```
114132

115-
To bind the library operating system to the application, we have to add the crate [hermit-sys](https://crates.io/crates/hermit-sys) to the dependencies in the file `Cargo.toml`.
133+
To bind the library operating system to the application, we have to add the crate [`hermit-sys`](https://crates.io/crates/hermit-sys) to the dependencies in the file `Cargo.toml`:
116134

117135
```toml
118136
# Cargo.toml
@@ -130,7 +148,7 @@ Finally, the application can be build with the common command `cargo build`.
130148

131149
The result is a 64-bit excutable in the [executable link format](https://refspecs.linuxfoundation.org/elf/elf.pdf) (ELF).
132150
To start the application within a common virtual machine, a loader is required, which initialize the processor and start the applications.
133-
We provide at [GitHub](https://github.com/hermitcore/rusty-loader) a simple loader.
151+
We provide a simple loader on [GitHub](https://github.com/hermitcore/rusty-loader).
134152
A makefile to build the loader is part of the project.
135153
After that, Qemu can be used to start RustyHermit in a VM as follows:
136154

@@ -144,8 +162,10 @@ To improve the performance, KVM can be used to use the virtualization extension
144162
qemu-system-x86_64 -display none -smp 1 -m 64M -serial stdio -kernel path_to_loader/rusty-loader -initrd path_to_hello_world/hello_world -enable-kvm -cpu host
145163
```
146164

147-
For the near future, we have to stabilized the interface to the hardware.
165+
### Roadmap
166+
167+
For the near future, we plan to stabilize the interface to the hardware.
148168
For instance, the support of [Virtio-fs](https://virtio-fs.gitlab.io/)
149169
is in an early stage. In addition, the integration into Rust standard
150-
library isn't finalized and the current version runs only on x86. In the
151-
future, we want to support also aarch64 as processor architecture.
170+
library isn't finalized yet and the current version runs only on x86. In the
171+
future, we want to also support aarch64 as processor architecture.
File renamed without changes.

0 commit comments

Comments
 (0)