Binary Compatibility In Unikraft

Let’s hack and run our favorite applications on top of Unikernels using the Unikraft toolkit. Unikernel can enhance the performance by increasing the speed and lowering the response time and at the same time providing high-level security. To know more about Unikernels, kindly visit my previous blogs: https://chococandy63.github.io/chococandy-blog/tags/unikernel/

In this blog, I will teach you about binary compatibility in Unikraft.

We can port applications to Unikraft(future blogs will show you how you can port applications to Unikraft) but that will take time and might be a little complex if you don’t like to play with low-level C stuff.

No worries, we have an alternate solution for this which is to take the pre-complied application binaries of existing applications/command line utilities and run them on top of Unikernel using Unikraft tooling.

I have done the same for the grep command line utility. You can see my work here: https://github.com/unikraft/dynamic-apps/pull/71

Note: These applications are Linux executables and they are not ported to Unikraft. They just run it on top of unikraft as Unikernels.

Let us go through the steps that I followed in order to run grep on Unikraft.

Commands to follow

which grep

Outputs: /usr/bin/grep

file /usr/bin/grep

Outputs: /usr/bin/grep: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=492b58120241302624ff65d4f8867f3e82713545, for GNU/Linux 3.2.0, stripped

Let’s take another example of a little more complex application like-

Suppose we want to run a Rust application on Unikraft, we check the file information using file command -> outputs as 64 bit ELF.

Internals

We run ldd app-name which shows the shared object dependencies. In order for app-name to run properly we need these dependencies. We can also see the file systems in a more structured way by using a tree command.

We found a file named ld-linux-x86-64.so.2 which is basically a dynamic linker/loader. This is a system loader app that Linux calls when loading stuff in memory. Every time you run any executable, Linux will run this program and load all the dependencies that the executable has. So, we also want to do the same when we are running an application on Unikraft.

We have run.sh script inside run-app-elfloader repository which is a wrapper on top of a QEMU, this script just makes it easier to run the application on top of QEMU without mentioning/configuring the QEMU flags(because those flags are being handled internally by run.sh script).

To run any application- ./run.sh -r ../dynamic-apps/lang/rust/ -k ./run-app-elfloader_qemu-x86_64_plain /filename

You probably know by now what run.sh script does, moving to the -r flag which is used to link the location of the app