This blog post discusses two newly discovered CVEs affecting Eclipse ThreadX before version 6.4.0: CVE-2024-2214 and CVE-2024-2212. Discovered by Humanativa Group, these vulnerabilities involve low-level memory exploits, including buffer overflows and integer wraparounds. Eclipse ThreadX is an open-source real-time operating system for embedded devices, formerly known as Azure RTOS. The blog emphasizes the importance of properly understanding and communicating the scope of vulnerabilities in popular software. Tools like ObjectSecurity’s BinLens™ (formerly ObjectSecurity OT.AI Platform) can help detect and remediate such vulnerabilities efficiently.

Two new CVEs (CVE-2024-2214, CVE-2024-2212) affecting Eclipse ThreadX at versions before 6.4.0 were recently discovered by Humanativa Group on May 26th, 2024. You can find Humanativa’s blog post about the disclosure here. Furthermore, GitHub user 0xdea documents the findings here. These vulnerabilities both involve low-level memory exploits (buffer overflows and integer wrap arounds).

When Microsoft transferred ownership of Azure RTOS to the Eclipse foundation, the project was rebranded as Eclipse ThreadX. Eclipse ThreadX is an open-source real time operating system (RTOS) for embedded devices. You can view the GitHub repository for Eclipse ThreadX here. Eclipse ThreadX is a widely adopted dependency used in many embedded systems and IoT devices. Vulnerabilities found in Eclipse ThreadX are positioned to cause a high degree of damage, should they go unaddressed.

I felt that the existing 3rd-party articles documenting these CVEs insufficiently describe their details, at least those details that I am interested in. Most notably, I could not find information regarding what devices are affected by these CVEs. With this context, this blog post seeks to deep dive into these CVEs, figuring out how they work and what embedded/IoT devices they affect.

CVE-2024-2214

This CVE has been published to the NVD here. The NVD describes this CVE as:

In Eclipse ThreadX before version 6.4.0, the _Mtxinit() function in the Xtensa port was missing an array size check causing a memory overwrite. The affected file was ports/xtensa/xcc/src/tx_clib_lock.c.

As I already mentioned, this vulnerability affects Eclipse ThreadX versions before 6.4.0. You can view the commit which fixes the vulnerability here. This commit is included in version 6.4.0 of Eclipse ThreadX, resolving the vulnerability.

When reading this CVE’s description, I had a few questions. What is the _Mtxinit() function? What is an Xtensa port? What array check was missed to cause the memory overwrite?

Xtensa is a type of microprocessor developed by Tensilica Inc. You can read about them here. Eclipse ThreadX has several ports. These ports are directories which include architecture and compiler specific source code files. This is illustrated in the source code directory breakdown below:

Eclipse ThreadX Source Code Directory Breakdown

The source code in these ports is only compiled into the final build of Eclipse ThreadX if the build is targeting the corresponding architecture and compiler. Because CVE-2024-2214 is found in ports/xtensa/xcc/src/tx_clib_lock.c, it will only be compiled into builds targeting Xtensa processors.

As its name suggests, Eclipse ThreadX supports multithreading. When used as a dependency, it allows embedded systems to spawn multiple threads of processing at once. When two threads attempt to access a shared resource simultaneously, undefined behavior can occur, causing program crashes and other issues. To prevent this, mutexes (mutually exclusive flags) are used. Mutexes prevent multiple threads from accessing a shared resource at once. Eclipse ThreadX allows developers to create mutexs for this purpose.

The _Mtxinit() function is called whenever a mutex is initiated (hence the name) by the Xtensa C library or newlib C library that is distributed with Xtensa Tools. Let’s look at _Mtxinit()’s source code:

_Mtxinit() Source Code

When called, _Mtxinit() initializes a new mutex using the tx_mutex_create function defined by the ThreadX API. This mutex is stored in the xclib_locks global variable. xclib_locks is an array of size XT_NUM_CLIB_LOCKS, meaning it can only store a finite number of mutexes at once.

Whenever _Mtxinit() is called, it increments the counter called lcnt. lcnt can be incremented to a value higher than the size of xclib_locks. When this happens, there is a memory overwrite, causing the CVE. Memory overwrites can cause undefined behavior and can be manipulated by savvy attackers to do damage. This particular CVE can be exploited if an attacker is able to initialize a large number of mutexes simultaneously, if such a thing is possible in upstream code.

Funnily enough, the developer who wrote this code made a note of this issue, labelling it /* Fatal error */, as you can see in the source code. The developer even included an if statement to check for the condition where lcnt exceeds the size of xclib_locks, although they didn’t programmatically address the issue in any way.

The fix for this CVE was rather trivial, as is shown in the commit mentioned earlier:

_Mtxinit() Source Code – Fixed

After this investigation, I summarized what devices this CVE affects in the following statement:

CVE-2024-2214 only affects embedded devices that are running Eclipse ThreadX before version 6.4.0, have Xtensa processors, and create many mutexes simultaneously.

CVE-2024-2212

The second CVE has been published to the NVD here. The NVD describes this CVE as:

In Eclipse ThreadX before 6.4.0, xQueueCreate() and xQueueCreateSet() functions from the FreeRTOS compatibility API (utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c) were missing parameter checks. This could lead to integer wraparound, under-allocations and heap buffer overflows.

The commit addressing this vulnerability (which is included in version 6.4.0 of Eclipse ThreadX) can be found here.

Just like before, when reading the description of this CVE, I had a couple questions. What is the FreeRTOS compatibility API? What are the xQueueCreate() and xQueueCreateSet() functions? What parameter checks were missing?

To help ease migration to ThreadX RTOS, Eclipse ThreadX supports adaptation layers for various legacy RTOS APIs, one of which is FreeRTOS. Programs which depend upon the FreeRTOS API may instead use Eclipse ThreadX under the hood by interacting with this FreeRTOS compatibility API.

The FreeRTOS compatibility API implements various functions defined by the original FreeRTOS specification. Two of these functions are xQueueCreate() and xQueueCreateSet(). FreeRTOS allows for the creation of tasks and queues. Tasks are similar to threads, and queues enable messages to be passed between tasks. Under the hood, ThreadX uses its own internal data structures (i.e., threads, semaphores, etc.) to support the FreeRTOS API functions such as xQueueCreate() and xQueueCreateSet(). You can read more about FreeRTOS queues here.

The way xQueueCreate() and xQueueCreateSet() were implemented in the ThreadX FreeRTOS adaptation layer allows for integer wraparounds. An integer wraparound occurs when an integer value is incremented to a value that is too large to store in the associated bit representation. When this occurs, increasing the value will cause a large number to become a very small number.

Let’s look at the source code for xQueueCreate().

xQueueCreate() Source Code

On line 1536, mem_size amount of memory is allocated to hold the queue being created. On line 1534, we see that mem_size is defined as uxQueueLength*(uxItemSize) (the length of the queue multiplied by the size of a single item in the queue). Because these arguments are controlled by the caller of the function, the caller can opt to set both values to be very large. When the values are made too large, this multiplication causes an integer wraparound. This integer wraparound results in a very small value for mem_size, a value that is much smaller than that which is needed to hold the queue being created.

The source code for xQueueCreateSet() has this same issue, so I am not including its source code in this blog post.

Just like before, the fix was rather trivial. The developer instead returns early from the function if the queue length is large enough to cause an integer wraparound.

xQueueCreate() Source Code – Fixed

Because xCreateQueue() and xCreateQueueSet() are part of an external API to be used by upstream code, the values of those parameters passed to the vulnerable functions depend on the upstream code. We can summarize what devices are affected by this CVE as such:

CVE-2024-2212 only affects embedded devices that are running Eclipse ThreadX before version 6.4.0 and are running applications which use the FreeRTOS compatibility layer API to create queues.

Conclusion

When news organizations write articles about CVEs, they sometimes under or overrepresent the number of devices that are affected. In this case, the devices affected represent only a small percentage of all devices running Eclipse ThreadX. However, in the future this could be reversed: the number of devices affected by a vulnerability could be greater than what popular reporting indicates. For this reason, we urge individuals to seek out reliable and detailed sources of information while researching a CVE that might affect them.

We place a lot of trust in open-source software, and open-source software is not immune to obvious, unpublished vulnerabilities. Detecting all these unpublished vulnerabilities manually can be quite difficult if not impossible. ObjectSecurity’s BinLens™ (formerly ObjectSecurity OT.AI Platform) detects memory vulnerabilities like those written about here, before they are published to the National Vulnerability Database as CVEs. With ObjectSecurity’s BinLens™ (formerly ObjectSecurity OT.AI Platform), you can detect binary weaknesses and vulnerabilities in a reliable, fast, automated way.