/GSoC-Shadow-Stack

Google Summer of Code 2022 Work Product Submission

Unikraft GSoC'22: Shadow Stack

Software based shadow stacks protect the return value of the functions by comparing what’s pushed into them with what resides in the traditional stack, practically, functioning as a backup and check storage.

The current implementation aims to bring the compiler based, LLVM ShadowCallStack to Unikraft apps.

What makes this project so different from other approaches is the complexity of the platform it targets. Unikraft, a Unikernel Development Kit, provides applications that run in a single address space, which means that there is no separation between usermode and kernelmode.

unikraft build system

Thus, traditional means of using the compiler based ShadowCallStack can not be applied to Unikraft images. More exactly, providing a runtime (not yet supported by LLVM's compiler-rt) for this security mechanism can not follow the path of using, for instance, the arch_prctl syscall, very nicely documented here.

Moreover, what's really so interesting about Unikraft is the ability of building images for a plethora of architectures and platforms, ergo, the initial goal of my GSoC project (Shadow Stack for AArch64 based apps) could easily come to light while maintaining separation and modularity.

unikraft architecture

Following this idea, what had to be accomplished was modifying the bootstraping process (provided by the ukboot internal library), by inserting a constructor, whose sole purpose was to initialize the x18 register with the protected stack.

Nevertheless, for more complex apps, such as SQLite, Redis and Nginx (already ported to Unikraft), initializing x18 means altering the scheduling implementation (found in the uksched and ukschedcoop internal libraries), as multithreading becomes the norm.

GSoC contributor

Name: Maria Sfiraiala

Email: maria.sfiraiala@gmail.com

Github profile: mariasfiraiala

Mentors

Razvan Deaconescu

Vlad Badoiu

Main Contributions

The biggest part of my work went into crafting the Shadow Stack PR, which should be upstream once the 0.12 Epimetheus Unikraft release is out.

This PR aims to bring Shadow Stack support to both single threaded and multithreading apps, even though work is still pending in order to fix some bugs regarding the multithreading Shadow Stack implementation.

Sidequests

Besides providing the aforementioned PR, critical to the full integration of my work was ensuring that the most used complex apps on the AArch64 architecture were functional.

This matrix, which can also be found here

App\Compiler gcc - x86 gcc - aarch64 clang - x86 clang - aarch64 clang with scs gcc-12 with scs
SQLite ✔️ ✔️ ✔️ ✔️ 🔜 🔜
redis ✔️ ✔️ ✔️ ✔️ 🔜 🔜
nginx ✔️ ✔️ ✔️ ✔️ 🔜 🔜

perfectly describes the efforts made into that direction.

PRs opened by me

PRs reviewed by me

Issues opened by me

Unikraft Summer of Code 2022

Unikraft Summer of Code is a unikernel and library OS workshop held every summer by the Unikraft community.

My contributions revolved around both reviewing and updating last year's content for the Complex Applications session and testing the content for the Contributing to Unikraft session.

For a better grasp of the work that went into it, check these 2 PRs:

Roadmap

My journey for the second part of the GSoC mentorship was documented here.

For more detailed timestamps you can check our meeting notes in the Unikraft meeting notes repo; look for the files with the ss prefix (acronym for Shadow Stack).

Blog posts

During GSoC'22, I provided 3 blog posts which offer a comprehensive status quo for the 3 months that I was involved with Unikraft:

Documentation

Documenting each and every step I took this summer was also one of my favourite activities.

The main 3 documents that highlight this passion are:

Current status

My project, even though it followed the initial proposal quite accurately, provides Shadow Stack support for apps without multithreading.

To be more exact, already implemented Unikraft apps, such as helloworld, or any user imported programs that do not use what, in the Unikraft realm, is considered multithreading work with Shadow Stack support.

As Proof of Concept, I relied on inspecting assembly code using gdb:

main (argc=1, argv=0x4013c3d0 <ukplat_entry_argp.argv>)
    at /home/maria/demo/02-hello-world-with-shadow-stack/apps/app-helloworld/main.c:27
27      {
(gdb) x/i $pc
=> 0x40108590 <main>:   str     x30, [x18], #8
(gdb) si
0x0000000040108594      27      {
(gdb) x/i $pc
=> 0x40108594 <main+4>: stp     x29, x30, [sp, #-48]!
(gdb) x/x $x18
0x47fc0018:     0x00000000
(gdb) x/x $x30
0x40113c78 <main_thread_func+380>:      0x7100001f
(gdb) x/x 0x47fc0010
0x47fc0010:     0x40113c78

Notice how [x18 - 8] stores pointer to x30, which at this point in time has the return address.

Future work

The first milestone to be achieved after GSoC'22 comes to an end is having multithreading Shadow Stack support.

Beautifying and easing the make build system for apps for which Unikraft users would like to have Shadow Stack support is also a top priority.

Reviewing current work done by the community towards modifying the scheduling API and updating my implementation to fit these changes takes a big part in my planning for the future 2-3 months.

Nevertheless, investigating other security mechanisms related to Shadow Stack (such as CET and Safe Stack) and providing proposals as to how they would be integrated into the Unikraft ecosystem seems to be critical to Unikraft's security, as it heavily relies on the isolation provided by running images in a virtualized medium, without any other significant security mechanisms being involved.

As a part of my testing work, I also plan on continuing to test Unikraft apps on AArch64 with various compilers. Some of these apps are: app-python3, app-lua, app-httpreply.

Another thing which should also be achieved is providing a series of patches for newlib in order to fix some gcc-isms that, for the time being, make the compilation of AArch64 apps impossible using clang.

Main takeaways

Soft skills

The achievement I am the proudest about is the easiness with which I, now, ask questions. Luckily, I've come to the conclusion that, mostly, people don't bite and having trouble and asking for help isn't such a sin.

The other accomplishment with which I'm also very happy is the integration among the other members of the community. I am now accustomed with everyone's role in the organization, what are the current tasks carried out by the team, what work is being done at the moment, who to ask about a particular bug. In other words, I've found my place.

Hard skills

Technologies I got accustomed with:

C  AArch64  SQLite  Redis  Nginx  Git  Docker  Markdown 

Final thoughts

My forever gratitude goes towards my mentors, Razvan and Vlad as they truly embodied what a mentor should be. Without them my project wouldn't have been as fun and as close to an end as it is now.

Many thanks to the people that also looked after me, Radu, Eduard, Stefan and Cezar.

To the rest of the community I pestered with issues and stupid questions, Michalis, Marc, Simon and Robert, my sincere apologies and thank you for your patience and willingness to help.