14 July 2021

Initial Finds from Running Our Application in CHERI

Our application

In basic terms our IoT collection device reads data from a sensor, it processes this signal and then runs it through a neural network and then sends the output to another device in the near vicinity.

Sensor Reading > Data filter > Neural Network > Transmitter.

We use the standard C++ deque to share data between these different modules.

First run using CHERI

Now that we have compiled our program to work with CHERI we will run it and see if we encounter any errors while running it.

On the first run we encountered an issue, so it looks like there is a potential security issue in this early version of our code. Below we will start debugging the issue.

Debugging the issue

Before debugging it is important to compile the application with debug flags which adds extra information to the binary which will help us debug. (-g when compiling directly or -DCMAKE_BUILD_TYPE=Debug when using CMake)

Next we just use gdb to run the application to see if we get a more verbose error, this then should give us a clue where to look for the problem.

So it looks like the actual problem is a bounds fault, as shown above the issue seems to link to register ca2. GDB will also supply a line number and file name where the exception occurred. If we run disas this shows us the assembly command that caused the exception. It looks like the CPU is trying to load a word from register a2 into a4 when the fault occurs.

GDB tells us that the issue occurs at line 300 in a file we use to do some of the data filtering. The value x is passed in as an argument to this function, the goal of this function is to provide the inverse square root of the input value.

Looking at line 300 it looks like it tries to cast y into a long. This code works on the assumption that the sizeof(long) and sizeof(float) are equal on the target platform. We are running this inside the riscv64-purecap VM, in riscv64 a long is 8 bytes and a float is 4 bytes which is why we are getting the capability bounds error.

Background to the issue we have found

This method of doing inverse square root is actually quite well documented and was initially used to get around the lack of instructions to do this efficiently. The SSE instruction set helped greatly with this meaning it no longer needs to be done this way on most machines.

However there may still be some use cases to this in lower powered embedded hardware with limited instruction sets. So this may need to be included on certain versions of our device or we may need to look into using the sqrt function from the C++ library to make this code more platform agnostic.

Use of this may also be considered an aliasing violation as it involves type-punning through pointer casting, which violates C/C++ strict aliasing rules.