The Devil in the Details: How The Caching Daemon Keeps Our Yocto Customers Running Safe

-It’s not always enough to just be safe, sometimes you need to be fast too.

RunSafe is in the business of helping developers – and the organizations that employ them – to reduce risk. A key part of purpose is making sure our customers have the right tools that work in an optimal way, which can vary by use-case.

There is a whole universe of memory-based attacks like stack, heap, buffer and a myriad of other types of overflow and memory abuse attacks that can be potential attack vectors. At RunSafe, our technology limits risk by not enabling attackers to weaponize memory bugs, even as those memory bugs continue to exist in the underlying software.

Among the many environments where RunSafe supports customers is in Yocto build environments, which are commonly used in the embedded space.  The Yocto Project is run by the Linux Foundation and is an open source effort that has found increasingly broad adoption. 

With our Alkemist:Source product, RunSafe provides load time function randomization (LFR) capabilities. It’s a security feature that can be added to compiled binaries, such that whenever the binary is loaded, it randomizes memory allocation and prevents certain types of attacks. RunSafe has a delivery model that enables the easy integration of the LFR into the Yocto build process, so that when you get your image at the end of the Yocto build, it has built-in protection.

Traditional Shared Library

With Yocto and  Alkemist:Source,  every time you boot your device, every time applications load, they look different to an attacker.  And no, this isn’t theoretical – it’s a simple 5 minutes process (we’ve outlined the process in a previous blog post – )

The Yocto Resource Utilization Challenge

We have many customers that use Alkemist: Source for one or two binaries. With Yocto, it’s not just one or two binaries that are being protected, it’s everything in the system and full image protection. 

When dealing with embedded devices that have limited resources, there can be different challenges than running a single binary that needs to be protected on a big server. That’s what happened with one of our customers that deployed Alkemist:Source for a Yocto build project on a resource constrained device.

What the organization found is when their image was built with LFR enabled, there was a measurable performance hit on startup; and, applications were taking longer to load than what they wanted. Now in this case, our customer had a really heavy startup procedure, which is not always the case for most embedded devices, so they were running on a slow processor.

We knew we had to come up with a solution to this problem. That’s where the caching daemon comes into the picture.

How the Caching Daemon Works

With Alkemist: Source, when a binary is loaded into memory it’s randomized.  With a shared library that creates some additional resource utilization. What happens is the randomization is actually a copy of that shared library existing in memory, because there’s a copy-on-write protection for the shared library.

So what in effect occurs is when the shared library loads, RunSafe randomizes it and it then copies it to a new memory location. So if 10 different applications are all using that shared library, they end up making 10 copies and randomizing it 10 different times. That leads to some memory bloat and can lead to a potential performance hit, especially on resource constrained devices, like the Yocto example that our customer was using.

The solution we came up with at RunSafe is to minimize the shared library memory randomization hit is the caching daemon. With the caching daemon, there is only one copy of the shared library that is randomized in memory. The one randomized copy in turn is used by all the other binaries that might link to the shared library.

Basically we keep a record of things in memory. Rather than re-randomize when we see a given shared object used again, we pass the location of that shared object already in memory for re-use.

Technical Details on Caching Daemon

RunSafe has a provisional patent on the caching daemon as it introduces a number of unique innovations. We took great pains to secure the daemon itself writing it in the open source Rust programming language, which has its own built-in security feature and is considered to be typesafe.

LFR Library Caching consists of two major components: a new cache daemon that keeps memory mappings for each loaded library and enforces security policy, and the existing libLFR, modified to communicate with the cache daemon. 

The cache daemon is responsible for caching code randomized by LFR. Before libLFR randomizes a library in a client process, it asks the daemon for a cached copy. If the daemon has a cached copy, it sends the file descriptor and additional relocation metadata for that library to the client process. 

To control the resource usage of the cache daemon and avoid caching libraries that are no longer in use, the daemon will have a tunable maximum cache size, specified in memory size or number of libraries. The daemon will evict libraries from the cache using a least recently used (LRU) strategy, so that frequently used libraries always stay in cache, as long as there is space. When the daemon evicts a library from the cache it will close the file descriptor. The kernel will then free the memory when the last process with that file mapped exits (or unloads the library).

Memory Safety that Respect Performance Demands

There is no shortage of academic research about how to limit the risks of memory attacks. While research is all fine and good, with Alkemist:Source, RunSafe is able to help organizations implement memory security in a practical way.

We have moved from just solving the first challenge of helping to mitigate memory risks, to help our customers with deeper underlying issues of performance and how we impact minimal resource systems.

You can have performance and you can have security.

RunSafe provides a simple and seamless option to completely eliminate zero-day and other memory-based vulnerabilities, without patching, for yocto developers. With a 5-minute one-time implementation into the native yocto build stage, RunSafe’s Alkemist technology immunizes binaries from memory attacks, so that every image is functionally identical but logically unique. This changes hacker economics back in favor of the manufacturers and users of embedded devices.

You can get started today by registering at alkemist.runsafesecurity.com.