What's in Your SOUP?
by Ralph Moore
March 2024
SOUP (Software of Unknown Provenance) is often incorporated into embedded system projects due to schedule pressure, lack of in-house expertise, or for other reasons, and it ends up in the final product. Such third-party software may be carefully designed, documented, and commented, but it remains a mystery to your team because no one has time to study it. Alternatively, it may be full of weaknesses that hackers love to exploit or it may even contain hacker back doors and trojan horses.
Short of expending scarce resources to study and possibly fix this third-party software, is there anything that you can do to protect the integrity of your system, in case it is bad news? Yes there is! SOUP can be safely put into an isolated partition from which it cannot be used to attack the rest of your system. This paper outlines a step-by-step approach to do this by using SecureSMX®, our next generation RTOS. SecureSMX provides the necessary tools to put SOUP into an isolated partition so strong that even the most spirited Trojan horse cannot break out. Partitioning also protects your embedded system from bugs in the SOUP.
Start
Figure 1 shows an embedded system with SOUP linked into the application code. Dashed lines in this figure indicate functional areas, not partitions. Boot & Initialize functions run following power on or system reboot. They run in non-task mode. When basic initialization is completed, control is transferred to System Services, which start the Application running in task mode. Code in all three areas is running in privileged mode (pmode).
Step 1
The first step is to separate the SOUP code and data from the application code and data and to put each into a separate partition, as shown in Figure 2, with solid lines.
Figure 2 shows the system after the MPU has been turned on and the SOUP Partition (SP) has been separated from the Application Partition (AP). Note that all code is still running in pmode. The application uses the default Memory Protection Array (MPA) shown in Figure 3a. All tasks in AP are assigned this MPA, by default. It is loaded into the MPU before each application task runs. The SOUP Partition (SP) uses the MPA shown in Figure 3b, which is loaded into the MPU before each of its tasks run.
This result is relatively easy to achieve. For Fig. 3a, nothing needs to be done, other than to turn on the MPU during initialization. For Fig 3b, add to project file Extra Options [1] of all C and assembly SOUP modules:
--section .bss=.soup_bss
--section .data=.soup_data
--section .text=.soup_text
--section .rodata=.soup_rodata
This converts section names assigned by the compiler, to the names for the SOUP partition, prior to linking. Next, in the linker command file, define sizes and region blocks like this:
define exported symbol scsz = 0x2000; /* soup code size (power of 2) */
define exported symbol sdsz = 0x1000; /* soup data size (power of 2) */
define block soup_code with size = scsz*7/8, alignment = scsz
{ro section .soup_text, ro section .soup_rodata};
define block soup_data with size = sdsz*5/8, alignment = sdsz
{rw section .soup_data, rw section .soup_bss};
These blocks are then included in rom_block and sram_block. The final step is to create the MPA template in a SOUP module:
MPA mpa_tmplt_soup =
{
RGN(0 | RA("sys_data") | V, PDATARW | SRD("sys_data") | RSI("sys_data")| EN, "sys_data"),
RGN(1 | RA("sys_code") | V, PCODE | SRD("sys_code") | RSI("sys_code")| EN, "sys_code"),
RGN(2 | RA("soup_data")| V, DATARW | SRD("soup_data")| RSIC(soupdsz) | EN, "soup_data"),
RGN(3 | RA("soup_code")| V, CODE | SRD("soup_code")| RSIC(soupcsz) | EN, "soup_code"),
RGN(4 | RA("svc_code") | V, CODE | SRD("svc_code") | RSIC(svcsz) | EN, "svc_code"),
RGN(5 | V, 0, "spare"), /* available for pmsg */
RGN(6 | V, 0, "spare"), /* available for pmsg */
RGN(7 | V, 0, "stack"), /* reserved for task stack */
};
This template is loaded into the MPA of each SOUP task, after it is created. Since SP is still running in pmode, all of its tasks can access all of the above regions. The stack region is loaded by the RTOS, before a task runs. At this point, very little code change has been made and the system should still run normally, except the MPU is providing some extra protection that might catch latent bugs in the SOUP such as uninitialized pointers.
Step 2
The next step is to change SP to use the Software Interrupt (SWI) interface for system calls via the Supervisor Call (SVC) exception. This is easily accomplished by adding the svc.c module to the project and including xapiu.h in all SOUP C files needing system services. svc.c converts system services such as smx_SemSignal() to svc shell functions such as smxu_SemSignal(). The latter shell functions implement SVC exceptions for system services. At this point, no additional code change has been made and the system should still run normally, except the SOUP partition may be slightly slower due to slower system calls. (The application tasks still make direct system calls and thus there is no impact upon them.)
Step 3
The final step is to move the SOUP partition into unprivileged mode, umode and to create a portal for it, if one is needed.
Fig. 4 shows the final result. Note that SP has been moved into umode, above the pmode barrier. The pmode barrier is enforced by hardware and cannot be penetrated from umode. SP can only communicate with the application via the portal (shown by a double line) and via the SWI for limited system services. Moving SP into umode simply requires setting the UMODE flag in the smx_TaskCreate() call for each SOUP task.
SecureSMX provides two types of portals for communication between partitions: free message portals and tunnel portals. Both make use of protected messages (pmsgs). A pmsg consists of a data block, which is sized and aligned as an MPU region, and a Message Control Block (MCB), which is linked to the data block. The MCB contains the region information for the data block (e.g. RBAR and RASR or RLAR), which is loaded into an empty MPU/MPA slot when the pmsg is received.
The free message portal is intended for commands and small amounts of data. The tunnel portal is intended for large multi-block data transfers. For each type, functions such as create, delete, open, close, send, and receive are provided by SecureSMX. Both portals use client/server protocols. Which end is which depends upon the SOUP. If it is like a file system, it would be the server. If it is a data acquisition subsystem, it might be the client. A task is needed at each end of a portal; however an existing task may do.
If the server has a function call API, it is necessary to create a shell function for each API function and a header file to map function names to shell function names. This is done in the client partition. Each shell function creates a pmsg for an API function that identifies the function and includes its parameters and data, if any. The pmsg is sent through the portal to the server. At the server end it is necessary to create a switch statement to convert pmsgs back into function calls, make the function calls, and then return results via the portal to the client. If the server also does client callbacks, a separate portal is required in the other direction.
Good examples of portals are included in SecureSMX. These are easily modifiable to create either type of portal. The new code required is normally small, simple, and highly repetitive.
Done
Once the portal requirement is met, the SOUP is fully isolated from the application. A hacker breaking into the SOUP partition cannot access application data nor execute application code. It is important to note that this has been accomplished with only minor changes and small additions to the application code and without requiring a deep understanding of the SOUP. This same technique can be applied to other vulnerable code in the application.
Notes
[1] All code examples are based upon IAR EWARM tools and the Arm Cortex v7M architecture processors. SecureSMX also supports Arm Cortex v8M architecture processors.
Ralph Moore is President of Micro Digital. A graduate of Caltech, he has served many roles at Micro Digital since founding it in 1975. Currently he is lead architect and programmer for SecureSMX.
Copyright © 2021-2024 Micro Digital, Inc. All rights reserved.
smx is a registered trademark of Micro Digital Inc. smx product names are trademarks of Micro Digital, Inc.
More Solution Papers
|