{"id":57097,"date":"2024-05-28T17:10:01","date_gmt":"2024-05-28T13:10:01","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/178817\/HNS-2024-06-threadx.txt"},"modified":"2024-05-28T17:10:01","modified_gmt":"2024-05-28T13:10:01","slug":"eclipse-threadx-buffer-overflows","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/eclipse-threadx-buffer-overflows\/","title":{"rendered":"Eclipse ThreadX Buffer Overflows"},"content":{"rendered":"<p>&#8211;[ HNS-2024-06 &#8211; HN Security Advisory &#8211; https:\/\/security.humanativaspa.it\/<\/p>\n<p>* Title: Multiple vulnerabilities in Eclipse ThreadX<br \/>* OS: Eclipse ThreadX &lt; 6.4.0<br \/>* Author: Marco Ivaldi &lt;marco.ivaldi@hnsecurity.it&gt;<br \/>* Date: 2024-05-28<br \/>* CVE IDs and severity:<br \/>* CVE-2024-2214 &#8211; High &#8211; 7.0 &#8211; CVSS:3.1\/AV:L\/AC:H\/PR:N\/UI:R\/S:U\/C:H\/I:H\/A:H<br \/>* CVE-2024-2212 &#8211; High &#8211; 7.3 &#8211; CVSS:3.1\/AV:L\/AC:L\/PR:N\/UI:R\/S:U\/C:H\/I:H\/A:L<br \/>* CVE-2024-2452 &#8211; High &#8211; 7.0 &#8211; CVSS:3.1\/AV:N\/AC:H\/PR:N\/UI:N\/S:U\/C:L\/I:H\/A:L<br \/>* Advisory URLs: <br \/>* https:\/\/github.com\/eclipse-threadx\/threadx\/security\/advisories\/GHSA-vmp6-qhp9-r66x<br \/>* https:\/\/github.com\/eclipse-threadx\/threadx\/security\/advisories\/GHSA-v9jj-7qjg-h6g6<br \/>* https:\/\/github.com\/eclipse-threadx\/netxduo\/security\/advisories\/GHSA-h963-7vhw-8rpx<br \/>* Vendor URL: https:\/\/threadx.io\/<\/p>\n<p>&#8211;[ 0 &#8211; Table of contents<\/p>\n<p>1 &#8211; Summary<br \/>2 &#8211; Background<br \/>3 &#8211; Vulnerabilities<br \/>3.1 &#8211; CVE-2024-2214 &#8211; Ineffective array size check and static buffer overflow in Eclipse ThreadX<br \/>3.2 &#8211; CVE-2024-2212 &#8211; Integer wraparounds, under-allocations, and heap buffer overflows in in Eclipse ThreadX<br \/>3.3 &#8211; CVE-2024-2452 &#8211; Integer wraparound, under-allocation, and heap buffer overflow in Eclipse ThreadX NetX Duo<br \/>3.4 &#8211; Other bugs with potential security implications in Eclipse ThreadX NetX Duo and USBX<br \/>4 &#8211; Affected products<br \/>5 &#8211; Remediation<br \/>6 &#8211; Disclosure timeline<br \/>7 &#8211; Acknowledgments<br \/>8 &#8211; References<\/p>\n<p>&#8211;[ 1 &#8211; Summary<\/p>\n<p>&#8220;Why don\u2019t you pick on projects your own size, <br \/>quit tormenting the tiny ones!&#8221; <br \/>&#8212; The Grugq<\/p>\n<p>Azure RTOS was Microsoft&#8217;s real-time operating system for IoT devices. At the<br \/>beginning of 2024, Microsoft contributed the Azure RTOS technology to the<br \/>Eclipse Foundation [1]. With the Eclipse Foundation as its new home, Azure RTOS<br \/>was rebranded as Eclipse ThreadX.<\/p>\n<p>Eclipse ThreadX is an advanced embedded development suite including a small but<br \/>powerful operating system that provides reliable, ultra-fast performance for<br \/>resource-constrained devices. It offers a vendor-neutral, open source, safety<br \/>certified OS for real-time applications, all under a permissive license. <\/p>\n<p>We reviewed ThreadX&#8217;s source code hosted on GitHub [2] and identified multiple<br \/>security vulnerabilities that may cause memory corruption. Their impacts range<br \/>from denial of service to potential arbitrary code execution.<\/p>\n<p>&#8211;[ 2 &#8211; Background<\/p>\n<p>Continuing our recent vulnerability research work in the IoT space [3] [4] [5],<br \/>we keep assisting open-source projects in finding and fixing vulnerabilities by<br \/>reviewing their source code. In December 2023, Azure RTOS, which one month<br \/>later was rebranded as Eclipse ThreadX, was selected as a target of interest.<\/p>\n<p>During the source code review, we made use of our Semgrep C\/C++ ruleset [6] and<br \/>weggli pattern collection [7] to identify hotspots in code on which to focus<br \/>our attention.<\/p>\n<p>&#8211;[ 3 &#8211; Vulnerabilities<\/p>\n<p>The vulnerabilities resulting from our source code review are briefly described<br \/>in the following sections.<\/p>\n<p>&#8211;[ 3.1 &#8211; CVE-2024-2214 &#8211; Ineffective array size check and static buffer overflow in Eclipse ThreadX<\/p>\n<p>In Eclipse ThreadX before version 6.4.0, the `_Mtxinit()` function in the<br \/>Xtensa port was missing an array size check causing a memory overwrite.<\/p>\n<p>The vulnerability was spotted in the following file:<br \/>* \/ports\/xtensa\/xcc\/src\/tx_clib_lock.c<\/p>\n<p>There was no error handling in case `lcnt` &gt;= `XT_NUM_CLIB_LOCKS`. The program<br \/>would continue and the `tx_mutex_create()` would eventually corrupt memory by<br \/>writing outside the bounds of the `xclib_locks` static array:<br \/>&#8220;`c<br \/>#ifdef TX_THREAD_SAFE_CLIB \/* this file is only needed if using C lib *\/<br \/>&#8230;<br \/>#if XSHAL_CLIB == XTHAL_CLIB_XCLIB<br \/>&#8230;<br \/>static TX_MUTEX xclib_locks[XT_NUM_CLIB_LOCKS];<br \/>static uint32_t lcnt;<br \/>&#8230;<br \/>\/**************************************************************************\/<br \/>\/* _Mtxinit &#8211; initialize a lock. Called once for each lock. *\/<br \/>\/**************************************************************************\/<br \/>void<br \/>_Mtxinit (_Rmtx * mtx)<br \/>{<br \/>TX_MUTEX * lock;<\/p>\n<p>if (lcnt &gt;= XT_NUM_CLIB_LOCKS) { \/\/ VULN: empty if() body<br \/>\/* Fatal error *\/<br \/>}<\/p>\n<p>lock = &amp;(xclib_locks[lcnt]);<br \/>lcnt++;<\/p>\n<p>\/* See notes for newlib case below. *\/<br \/>#ifdef THREADX_TESTSUITE<br \/>tx_mutex_create (lock, &#8220;Clib lock&#8221;, 0);<br \/>#else<br \/>tx_mutex_create (lock, &#8220;Clib lock&#8221;, TX_INHERIT);<br \/>#endif<\/p>\n<p>*mtx = lock;<br \/>}<br \/>&#8220;`<\/p>\n<p>Fixes:<br \/>https:\/\/github.com\/eclipse-threadx\/threadx\/pull\/340<\/p>\n<p>See also:<br \/>https:\/\/github.com\/eclipse-threadx\/threadx\/security\/advisories\/GHSA-vmp6-qhp9-r66x<\/p>\n<p>&#8211;[ 3.2 &#8211; CVE-2024-2212 &#8211; Integer wraparounds, under-allocations, and heap buffer overflows in in Eclipse ThreadX<\/p>\n<p>In Eclipse ThreadX before version 6.4.0, functions `xQueueCreate()` and<br \/>`xQueueCreateSet()` from the FreeRTOS compatibility API were missing parameter<br \/>checks. This could lead to integer wraparound, under-allocations, and heap<br \/>buffer overflows.<\/p>\n<p>The vulnerabilities were spotted in the following file:<br \/>* \/utility\/rtos_compatibility_layers\/FreeRTOS\/tx_freertos.c<\/p>\n<p>If an attacker could control `uxQueueLength` or `uxItemSize`, they could cause<br \/>an integer wraparound thus causing `txfr_malloc()` to allocate a small amount<br \/>of memory, exposing to subsequent heap buffer overflows (AKA BadAlloc-style<br \/>memory corruption):<br \/>&#8220;`c<br \/>QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize)<br \/>{<br \/>txfr_queue_t *p_queue;<br \/>void *p_mem;<br \/>size_t mem_size;<br \/>UINT ret;<\/p>\n<p>configASSERT(uxQueueLength != 0u);<br \/>configASSERT(uxItemSize &gt;= sizeof(UINT));<\/p>\n<p>#if (TX_FREERTOS_AUTO_INIT == 1)<br \/>if(txfr_initialized != 1u) {<br \/>tx_freertos_auto_init();<br \/>}<br \/>#endif<\/p>\n<p>p_queue = txfr_malloc(sizeof(txfr_queue_t));<br \/>if(p_queue == NULL) {<br \/>return NULL;<br \/>}<\/p>\n<p>mem_size = uxQueueLength*(uxItemSize);<\/p>\n<p>p_mem = txfr_malloc(mem_size); \/\/ VULN: integer wraparound and under-allocation<br \/>if(p_mem == NULL) {<br \/>txfr_free(p_queue);<br \/>return NULL;<br \/>}<\/p>\n<p>TX_MEMSET(p_mem, 0, mem_size);<br \/>TX_MEMSET(p_queue, 0, sizeof(*p_queue));<br \/>p_queue-&gt;allocated = 1u;<br \/>p_queue-&gt;p_mem = p_mem;<br \/>p_queue-&gt;id = TX_QUEUE_ID;<\/p>\n<p>p_queue-&gt;p_write = (uint8_t *)p_mem;<br \/>p_queue-&gt;p_read = (uint8_t *)p_mem;<br \/>p_queue-&gt;msg_size = uxItemSize;<br \/>p_queue-&gt;queue_length = uxQueueLength;<\/p>\n<p>ret = tx_semaphore_create(&amp;p_queue-&gt;read_sem, &#8220;&#8221;, 0u);<br \/>if(ret != TX_SUCCESS) {<br \/>return NULL;<br \/>}<\/p>\n<p>ret = tx_semaphore_create(&amp;p_queue-&gt;write_sem, &#8220;&#8221;, uxQueueLength);<br \/>if(ret != TX_SUCCESS) {<br \/>return NULL;<br \/>}<\/p>\n<p>return p_queue;<br \/>}<br \/>&#8220;`<\/p>\n<p>If an attacker could control `uxEventQueueLengthi`, they could cause an integer<br \/>wraparound thus causing `txfr_malloc()` to allocate a small amount of memory,<br \/>exposing to subsequent heap buffer overflows (AKA BadAlloc-style memory<br \/>corruption):<br \/>&#8220;`c<br \/>QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength)<br \/>{<br \/>txfr_queueset_t *p_set;<br \/>void *p_mem;<br \/>ULONG queue_size;<br \/>UINT ret;<\/p>\n<p>configASSERT(uxEventQueueLength != 0u);<\/p>\n<p>#if (TX_FREERTOS_AUTO_INIT == 1)<br \/>if(txfr_initialized != 1u) {<br \/>tx_freertos_auto_init();<br \/>}<br \/>#endif<\/p>\n<p>p_set = txfr_malloc(sizeof(txfr_queueset_t));<br \/>if(p_set == NULL) {<br \/>return NULL;<br \/>}<\/p>\n<p>queue_size = sizeof(void *) * uxEventQueueLength;<br \/>p_mem = txfr_malloc(queue_size); \/\/ VULN: integer wraparound and under-allocation<br \/>if(p_mem == NULL) {<br \/>txfr_free(p_set);<br \/>return NULL;<br \/>}<\/p>\n<p>ret = tx_queue_create(&amp;p_set-&gt;queue, &#8220;&#8221;, sizeof(void *) \/ sizeof(UINT), p_mem, queue_size);<br \/>if(ret != TX_SUCCESS) {<br \/>TX_FREERTOS_ASSERT_FAIL();<br \/>return NULL;<br \/>}<\/p>\n<p>return p_set;<br \/>}<br \/>&#8220;`<\/p>\n<p>These functions are part of an external API to be used by user&#8217;s applications.<br \/>The values of those parameters passed to the vulnerable functions depend on<br \/>user&#8217;s code.<\/p>\n<p>Fixes:<br \/>https:\/\/github.com\/eclipse-threadx\/threadx\/pull\/339<\/p>\n<p>See also:<br \/>https:\/\/github.com\/eclipse-threadx\/threadx\/security\/advisories\/GHSA-v9jj-7qjg-h6g6<\/p>\n<p>&#8211;[ 3.3 &#8211; CVE-2024-2452 &#8211; Integer wraparound, under-allocation, and heap buffer overflow in Eclipse ThreadX NetX Duo<\/p>\n<p>In Eclipse ThreadX NetX Duo before version 6.4.0, if an attacker could control<br \/>the parameters of `__portable_aligned_alloc()` they could cause an integer<br \/>wraparound and an allocation smaller than expected. This could cause subsequent<br \/>heap buffer overflows.<\/p>\n<p>The vulnerability was spotted in the following file:<br \/>* \/addons\/azure_iot\/azure_iot_security_module\/iot-security-module-core\/deps\/flatcc\/include\/flatcc\/portable\/paligned_alloc.h<\/p>\n<p>If an attacker could control the `size` or `alignment` arguments to the<br \/>`__portable_aligned_alloc()` function, they could cause an integer wraparound<br \/>thus causing `malloc()` to allocate a small amount of memory, exposing to<br \/>subsequent heap buffer overflows (AKA BadAlloc-style memory corruption):<br \/>&#8220;`c<br \/>static inline void *__portable_aligned_alloc(size_t alignment, size_t size)<br \/>{<br \/>char *raw;<br \/>void *buf;<br \/>size_t total_size = (size + alignment &#8211; 1 + sizeof(void *)); \/\/ VULN: integer wraparound<\/p>\n<p>if (alignment &lt; sizeof(void *)) {<br \/>alignment = sizeof(void *);<br \/>}<br \/>raw = (char *)(size_t)malloc(total_size); \/\/ VULN: under-allocation BadAlloc style<br \/>buf = raw + alignment &#8211; 1 + sizeof(void *);<br \/>buf = (void *)(((size_t)buf) &amp; ~(alignment &#8211; 1));<br \/>((void **)buf)[-1] = raw; \/\/ malloc ret is not checked; in case NULL is returned the program would crash here<br \/>return buf;<br \/>}<br \/>&#8220;`<\/p>\n<p>We spotted the same vulnerability in Azure IoT Preview source code at:<br \/>https:\/\/github.com\/azure-rtos\/azure-iot-preview\/blob\/master\/azure_iot\/azure_iot_security_module\/iot-security-module-core\/deps\/flatcc\/include\/flatcc\/portable\/paligned_alloc.h<\/p>\n<p>The maintainers confirmed the vulnerability, but informed us that the Azure IoT<br \/>Preview repository was not part of a product. Therefore, it was removed<br \/>entirely.<\/p>\n<p>Fixes:<br \/>https:\/\/github.com\/eclipse-threadx\/netxduo\/pull\/227<\/p>\n<p>See also:<br \/>https:\/\/github.com\/eclipse-threadx\/netxduo\/security\/advisories\/GHSA-h963-7vhw-8rpx<\/p>\n<p>&#8211;[ 3.4 &#8211; Other bugs with potential security implications in Eclipse ThreadX NetX Duo and USBX<\/p>\n<p>In addition to the vulnerabilities covered in the previous sections, we also<br \/>reported a few other bugs with potential security implications that were not<br \/>considered as vulnerabilities by Eclipse ThreadX maintainers. As such, our<br \/>reports were declassed to standard issues for code improvement.<\/p>\n<p>The first one is an unsafe use of the return value of `snprintf()` that we<br \/>observed in Eclipse ThreadX NetX Duo, in the following file:<br \/>* \/addons\/azure_iot\/nx_azure_iot_adu_agent.c<\/p>\n<p>The `snprintf()` API function returns the total length of the string it tried<br \/>to create, which could be larger than the actual length written; if an attacker<br \/>were able to craft input so that `update_id_length` became larger than<br \/>`NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE` and if the return value were used<br \/>unsafely (e.g., as an array index) somewhere else in the code, memory<br \/>corruption could have occured:<br \/>&#8220;`c<br \/>static UINT nx_azure_iot_adu_agent_reported_properties_state_send(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr)<br \/>{<\/p>\n<p>NX_PACKET *packet_ptr;<br \/>NX_AZURE_IOT_JSON_WRITER json_writer;<br \/>NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *manifest_content = &amp;(adu_agent_ptr -&gt; nx_azure_iot_adu_agent_update_manifest_content);<br \/>UINT status;<br \/>UINT result_code;<br \/>UINT i;<br \/>\/* Prepare the buffer for step name: such as: &#8220;step_0&#8221;, the max name is &#8220;step_xxx&#8221;. *\/<br \/>CHAR step_property_name[8] = &#8220;step_&#8221;;<br \/>UINT step_size = sizeof(&#8220;step_&#8221;) &#8211; 1;<br \/>UINT step_property_name_size;<br \/>UINT update_id_length;<br \/>&#8230;<br \/>\/* Fill installed update id. *\/<br \/>if ((adu_agent_ptr -&gt; nx_azure_iot_adu_agent_state == NX_AZURE_IOT_ADU_AGENT_STATE_IDLE) &amp;&amp; <br \/>(adu_agent_ptr -&gt; nx_azure_iot_adu_agent_update_manifest_content.steps_count))<br \/>{<\/p>\n<p>\/* Use nx_azure_iot_adu_agent_update_manifest as temporary buffer to encode the update id as string.*\/<br \/>update_id_length = (UINT)snprintf((CHAR *)adu_agent_ptr -&gt; nx_azure_iot_adu_agent_update_manifest,<br \/>NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE,<br \/>&#8220;{\\&#8221;%.*s\\&#8221;:\\&#8221;%.*s\\&#8221;,\\&#8221;%.*s\\&#8221;:\\&#8221;%.*s\\&#8221;,\\&#8221;%.*s\\&#8221;:\\&#8221;%.*s\\&#8221;}&#8221;,<br \/>sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_PROVIDER) &#8211; 1,<br \/>NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_PROVIDER,<br \/>manifest_content -&gt; update_id.provider_length, manifest_content -&gt; update_id.provider, <br \/>sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_NAME) &#8211; 1,<br \/>NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_NAME,<br \/>manifest_content -&gt; update_id.name_length, manifest_content -&gt; update_id.name,<br \/>sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_VERSION) &#8211; 1,<br \/>NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_VERSION,<br \/>manifest_content -&gt; update_id.version_length, manifest_content -&gt; update_id.version); \/\/ VULN: unsafe use of snprintf() return value<\/p>\n<p>if (nx_azure_iot_json_writer_append_property_with_string_value(&amp;json_writer,<br \/>(const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTALLED_CONTENT_ID,<br \/>sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTALLED_CONTENT_ID) &#8211; 1,<br \/>adu_agent_ptr -&gt; nx_azure_iot_adu_agent_update_manifest,<br \/>update_id_length)) \/\/ VULN: potentially large length is used to populate the &#8220;installedUpdateId&#8221; JSON property<br \/>{<br \/>nx_packet_release(packet_ptr);<br \/>return (NX_NOT_SUCCESSFUL);<br \/>}<br \/>}<br \/>&#8230;<br \/>&#8220;`<\/p>\n<p>We also spotted some potentially ineffective size checks due to assertions in<br \/>Eclipse ThreadX USBX, in the following files:<br \/>* \/common\/core\/src\/ux_hcd_sim_host_transaction_schedule.c<br \/>* \/common\/usbx_device_classes\/src\/ux_device_class_audio20_control_process.c<\/p>\n<p>If assertions were compiled-out in production code and `td -&gt;<br \/>ux_sim_host_td_length` was attacker-controlled, the `_ux_utility_memory_copy()`<br \/>function would have been able to write past the `slave_transfer_request -&gt;<br \/>ux_slave_transfer_request_setup` fixed-size (8 bytes) buffer:<br \/>&#8220;`c<br \/>UINT _ux_hcd_sim_host_transaction_schedule(UX_HCD_SIM_HOST *hcd_sim_host, UX_HCD_SIM_HOST_ED *ed)<br \/>{<\/p>\n<p>UX_DCD_SIM_SLAVE *dcd_sim_slave;<br \/>UX_HCD_SIM_HOST_TD *td;<br \/>UX_HCD_SIM_HOST_TD *head_td;<br \/>UX_HCD_SIM_HOST_TD *tail_td;<br \/>UX_HCD_SIM_HOST_TD *data_td;<br \/>UX_ENDPOINT *endpoint;<br \/>UX_SLAVE_ENDPOINT *slave_endpoint;<br \/>UX_DCD_SIM_SLAVE_ED *slave_ed;<br \/>ULONG slave_transfer_remaining;<br \/>UCHAR wake_host;<br \/>UCHAR wake_slave;<br \/>ULONG transaction_length;<br \/>ULONG td_length;<br \/>UX_SLAVE_TRANSFER *slave_transfer_request;<br \/>UX_TRANSFER *transfer_request;<br \/>ULONG endpoint_index;<br \/>UX_SLAVE_DCD *dcd;<\/p>\n<p>UX_PARAMETER_NOT_USED(hcd_sim_host);<\/p>\n<p>\/* Get the pointer to the DCD portion of the simulator. *\/<br \/>dcd = &amp;_ux_system_slave -&gt; ux_system_slave_dcd;<\/p>\n<p>\/* Check the state of the controller if OPERATIONAL . *\/<br \/>if (dcd -&gt; ux_slave_dcd_status != UX_DCD_STATUS_OPERATIONAL)<br \/>return(UX_ERROR);<\/p>\n<p>\/* Get the pointer to the candidate TD on the host. *\/<br \/>td = ed -&gt; ux_sim_host_ed_head_td;<\/p>\n<p>\/* Get the pointer to the endpoint. *\/<br \/>endpoint = ed -&gt; ux_sim_host_ed_endpoint;<\/p>\n<p>\/* Get the pointer to the transfer_request attached with this TD. *\/<br \/>transfer_request = td -&gt; ux_sim_host_td_transfer_request;<\/p>\n<p>\/* Get the index of the endpoint from the host. *\/<br \/>endpoint_index = endpoint -&gt; ux_endpoint_descriptor.bEndpointAddress &amp; ~(ULONG)UX_ENDPOINT_DIRECTION;<\/p>\n<p>\/* Get the address of the device controller. *\/<br \/>dcd_sim_slave = (UX_DCD_SIM_SLAVE *) dcd -&gt; ux_slave_dcd_controller_hardware;<\/p>\n<p>\/* Get the endpoint as seen from the device side. *\/<br \/>#ifdef UX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT<br \/>slave_ed = ((endpoint -&gt; ux_endpoint_descriptor.bEndpointAddress == 0) ?<br \/>&amp;dcd_sim_slave -&gt; ux_dcd_sim_slave_ed[0] :<br \/>((endpoint -&gt; ux_endpoint_descriptor.bEndpointAddress &amp; UX_ENDPOINT_DIRECTION) ?<br \/>&amp;dcd_sim_slave -&gt; ux_dcd_sim_slave_ed_in[endpoint_index] :<br \/>&amp;dcd_sim_slave -&gt; ux_dcd_sim_slave_ed[endpoint_index]));<br \/>#else<br \/>slave_ed = &amp;dcd_sim_slave -&gt; ux_dcd_sim_slave_ed[endpoint_index];<br \/>#endif<\/p>\n<p>\/* Is this ED used? *\/<br \/>if ((slave_ed -&gt; ux_sim_slave_ed_status &amp; UX_DCD_SIM_SLAVE_ED_STATUS_USED) == 0)<br \/>return(UX_ERROR);<\/p>\n<p>\/* Is this ED ready for transaction or stalled ? *\/<br \/>if ((slave_ed -&gt; ux_sim_slave_ed_status &amp; (UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER | UX_DCD_SIM_SLAVE_ED_STATUS_STALLED)) == 0)<br \/>return(UX_ERROR);<\/p>\n<p>\/* Get the logical endpoint from the physical endpoint. *\/<br \/>slave_endpoint = slave_ed -&gt; ux_sim_slave_ed_endpoint;<\/p>\n<p>\/* Get the pointer to the transfer request. *\/<br \/>slave_transfer_request = &amp;slave_endpoint -&gt; ux_slave_endpoint_transfer_request;<\/p>\n<p>\/* Check the phase for this transfer, if this is the SETUP phase, treatment is different. Explanation of how <br \/>control transfers are handled in the simulator: if the data phase is OUT, we handle it immediately, meaning we <br \/>send all the data to the device and remove the STATUS TD in the same scheduler call. If the data phase is IN, we <br \/>only take out the SETUP TD and handle the data phase like any other non-control transactions (i.e. the scheduler <br \/>calls us again with the DATA TDs). *\/<br \/>if (td -&gt; ux_sim_host_td_status &amp; UX_HCD_SIM_HOST_TD_SETUP_PHASE)<br \/>{<\/p>\n<p>\/* For control transfer, stall is for protocol error and it&#8217;s cleared any time when SETUP is received *\/<br \/>slave_ed -&gt; ux_sim_slave_ed_status &amp;= ~(ULONG)UX_DCD_SIM_SLAVE_ED_STATUS_STALLED;<\/p>\n<p>\/* Validate the length to the setup transaction buffer. *\/<br \/>UX_ASSERT(td -&gt; ux_sim_host_td_length == 8); \/\/ VULN: if assertions are compiled-out in production code, this check is ineffective<\/p>\n<p>\/* Reset actual data length (not including SETUP received) so far. *\/<br \/>slave_transfer_request -&gt; ux_slave_transfer_request_actual_length = 0;<\/p>\n<p>\/* Move the buffer from the host TD to the device TD. *\/<br \/>_ux_utility_memory_copy(slave_transfer_request -&gt; ux_slave_transfer_request_setup,<br \/>td -&gt; ux_sim_host_td_buffer,<br \/>td -&gt; ux_sim_host_td_length); \/* Use case of memcpy is verified. *\/ \/\/ VULN: potential buffer overflow due to ineffective size check<br \/>&#8220;`<\/p>\n<p>If assertions were compiled-out in production code and `data_length` was<br \/>attacker-controlled, the `_ux_utility_memory_copy()` function would have been<br \/>able to write past the `transfer -&gt; ux_slave_transfer_request_data_pointer`<br \/>buffer:<br \/>&#8220;`c<br \/>&#8230;<br \/>UINT _ux_device_class_audio20_control_process(UX_DEVICE_CLASS_AUDIO *audio,<br \/>UX_SLAVE_TRANSFER *transfer,<br \/>UX_DEVICE_CLASS_AUDIO20_CONTROL_GROUP *group)<br \/>{<\/p>\n<p>UX_SLAVE_ENDPOINT *endpoint;<br \/>UX_DEVICE_CLASS_AUDIO20_CONTROL *control;<br \/>UCHAR request;<br \/>UCHAR request_type;<br \/>UCHAR unit_id;<br \/>UCHAR control_selector;<br \/>UCHAR channel_number;<br \/>ULONG request_length;<br \/>ULONG data_length;<br \/>ULONG i;<br \/>ULONG n_sub, pos, min, max, res, freq;<\/p>\n<p>\/* Get instances. *\/<br \/>endpoint = &amp;audio -&gt; ux_device_class_audio_device -&gt; ux_slave_device_control_endpoint;<br \/>transfer = &amp;endpoint -&gt; ux_slave_endpoint_transfer_request;<\/p>\n<p>\/* Extract all necessary fields of the request. *\/<br \/>request = *(transfer -&gt; ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_REQUEST);<br \/>request_type = *(transfer -&gt; ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_REQUEST_TYPE);<br \/>unit_id = *(transfer -&gt; ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_ENEITY_ID);<br \/>control_selector = *(transfer -&gt; ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_CONTROL_SELECTOR);<br \/>channel_number = *(transfer -&gt; ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_CHANNEL_NUMBER);<br \/>request_length = _ux_utility_short_get(transfer -&gt; ux_slave_transfer_request_setup + UX_SETUP_LENGTH);<\/p>\n<p>for (i = 0; i &lt; group -&gt; ux_device_class_audio20_control_group_controls_nb; i ++)<br \/>{<br \/>control = &amp;group -&gt; ux_device_class_audio20_control_group_controls[i];<\/p>\n<p>\/* Reset change map. *\/<br \/>control -&gt; ux_device_class_audio20_control_changed = 0;<\/p>\n<p>\/* Is this request a clock unit request? *\/<br \/>if (unit_id == control -&gt; ux_device_class_audio20_control_cs_id)<br \/>{<\/p>\n<p>\/* Clock Source request.<br \/>* We only support Sampling Frequency Control here.<br \/>* The Sampling Frequency Control must support the CUR and RANGE(MIN, MAX, RES) attributes.<br \/>*\/<br \/>&#8230;<br \/>\/* We just support sampling frequency control, GET request. *\/<br \/>if ((request_type &amp; UX_REQUEST_DIRECTION) == UX_REQUEST_IN &amp;&amp;<br \/>(control_selector == UX_DEVICE_CLASS_AUDIO20_CS_SAM_FREQ_CONTROL))<br \/>{<\/p>\n<p>switch(request)<br \/>{<br \/>case UX_DEVICE_CLASS_AUDIO20_CUR:<\/p>\n<p>\/* Check request parameter. *\/<br \/>if (request_length &lt; 4)<br \/>break;<\/p>\n<p>\/* Send sampling frequency. *\/<br \/>if (control -&gt; ux_device_class_audio20_control_sampling_frequency)<br \/>_ux_utility_long_put(transfer -&gt; ux_slave_transfer_request_data_pointer, control -&gt; ux_device_class_audio20_control_sampling_frequency);<br \/>else<br \/>_ux_utility_long_put(transfer -&gt; ux_slave_transfer_request_data_pointer, control -&gt; ux_device_class_audio20_control_sampling_frequency_cur);<br \/>_ux_device_stack_transfer_request(transfer, 4, request_length);<br \/>return(UX_SUCCESS);<\/p>\n<p>case UX_DEVICE_CLASS_AUDIO20_RANGE:<\/p>\n<p>\/* Check request parameter. *\/<br \/>if (request_length &lt; 2)<br \/>break;<\/p>\n<p>if (control -&gt; ux_device_class_audio20_control_sampling_frequency == 0)<br \/>{<\/p>\n<p>\/* Send range parameters, RANGE is customized. *\/<br \/>UX_ASSERT(control -&gt; ux_device_class_audio20_control_sampling_frequency_range != UX_NULL);<\/p>\n<p>\/* Get wNumSubRanges. *\/<br \/>n_sub = _ux_utility_short_get(control -&gt; ux_device_class_audio20_control_sampling_frequency_range);<br \/>UX_ASSERT(n_sub &gt; 0);<\/p>\n<p>\/* Calculate length, n_sub is 16-bit width, result not overflows ULONG. *\/<br \/>data_length = 2 + n_sub * 12;<br \/>UX_ASSERT(data_length &lt;= UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH); \/\/ VULN: if assertions are compiled-out in production code, this check is ineffective<\/p>\n<p>\/* Copy data. *\/<br \/>data_length = UX_MIN(data_length, request_length);<br \/>_ux_utility_memory_copy(transfer -&gt; ux_slave_transfer_request_data_pointer,<br \/>control -&gt; ux_device_class_audio20_control_sampling_frequency_range,<br \/>data_length); \/* Use case of memcpy is verified. *\/ \/\/ VULN: potential buffer overflow due to ineffective size check<br \/>&#8230;<br \/>&#8220;`<\/p>\n<p>Please note that there may be other instances\/variants of these last bugs.<br \/>Therefore, a thorough assessment of all assertions used to check buffer sizes<br \/>in Eclipse ThreadX codebase is recommended.<\/p>\n<p>Finally, in Eclipse ThreadX USBX before pull request #161 was merged, there was<br \/>a memory copy with unchecked size in the<br \/>`_ux_host_class_pima_storage_info_get()` function in the following file:<br \/>* \/common\/usbx_host_classes\/src\/ux_host_class_pima_storage_info_get.c<\/p>\n<p>There was no size check for the two memory copy operations via the<br \/>`_ux_utility_memory_copy()` function marked below. Therefore, a write past the<br \/>end of the fixed size (256 bytes) buffer `storage -&gt;<br \/>ux_host_class_pima_storage_description` could have occured:<br \/>&#8220;`c<br \/>UINT _ux_host_class_pima_storage_info_get(UX_HOST_CLASS_PIMA *pima,<br \/>UX_HOST_CLASS_PIMA_SESSION *pima_session,<br \/>ULONG storage_id, UX_HOST_CLASS_PIMA_STORAGE *storage)<br \/>{<\/p>\n<p>UX_HOST_CLASS_PIMA_COMMAND command;<br \/>UINT status;<br \/>UCHAR *storage_buffer;<br \/>UCHAR *storage_pointer;<br \/>ULONG unicode_string_length;<\/p>\n<p>\/* If trace is enabled, insert this event into the trace buffer. *\/<br \/>UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_STORAGE_INFO_GET, pima, storage_id, storage, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)<\/p>\n<p>\/* Check if this session is valid or not. *\/<br \/>if (pima_session -&gt; ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER)<br \/>return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN);<\/p>\n<p>\/* Check if this session is opened or not. *\/<br \/>if (pima_session -&gt; ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED)<br \/>return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN);<\/p>\n<p>\/* Issue command to get the storage IDs. 1 parameter. *\/<br \/>command.ux_host_class_pima_command_nb_parameters = 1;<\/p>\n<p>\/* Parameter 1 is the Storage ID. *\/<br \/>command.ux_host_class_pima_command_parameter_1 = storage_id;<\/p>\n<p>\/* Other parameters unused. *\/<br \/>command.ux_host_class_pima_command_parameter_2 = 0;<br \/>command.ux_host_class_pima_command_parameter_3 = 0;<br \/>command.ux_host_class_pima_command_parameter_4 = 0;<br \/>command.ux_host_class_pima_command_parameter_5 = 0;<\/p>\n<p>\/* Then set the command to GET_STORAGE_INFO. *\/<br \/>command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_GET_STORAGE_INFO;<\/p>\n<p>\/* Allocate some DMA safe memory for receiving the storage info block. *\/<br \/>storage_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_STORAGE_MAX_LENGTH);<br \/>if (storage == UX_NULL)<br \/>return(UX_MEMORY_INSUFFICIENT);<\/p>\n<p>\/* Issue the command. *\/<br \/>status = _ux_host_class_pima_command(pima, &amp;command, UX_HOST_CLASS_PIMA_DATA_PHASE_IN , storage_buffer,<br \/>UX_HOST_CLASS_PIMA_STORAGE_MAX_LENGTH, UX_HOST_CLASS_PIMA_STORAGE_MAX_LENGTH);<\/p>\n<p>\/* Check the result. If the result is OK, the storage info block was read properly. *\/<br \/>if (status == UX_SUCCESS)<br \/>{<br \/>\/* Uncompress the storage descriptor, at least the fixed part. *\/<br \/>_ux_utility_descriptor_parse(storage_buffer,<br \/>_ux_system_class_pima_object_structure,<br \/>UX_HOST_CLASS_PIMA_OBJECT_ENTRIES,<br \/>(UCHAR *) storage);<\/p>\n<p>\/* Copy the storage description field. Point to the beginning of the storage description string. *\/<br \/>storage_pointer = storage_buffer + UX_HOST_CLASS_PIMA_STORAGE_VARIABLE_OFFSET;<\/p>\n<p>\/* Get the unicode string length. *\/<br \/>unicode_string_length = (ULONG) *storage_pointer ;<\/p>\n<p>\/* Copy that string into the storage description field. *\/<br \/>_ux_utility_memory_copy(storage -&gt; ux_host_class_pima_storage_description, storage_pointer, unicode_string_length); \/* Use case of memcpy is verified. *\/ \/\/ VULN: unchecked copy size for a copy in a fixed size (256 bytes) buffer (UX_HOST_CLASS_PIMA_STORAGE_MAX_LENGTH used to dynamically allocate storage_buffer is 512 bytes)<\/p>\n<p>\/* Point to the volume label. *\/<br \/>storage_pointer = storage_buffer + UX_HOST_CLASS_PIMA_STORAGE_VARIABLE_OFFSET + unicode_string_length;<\/p>\n<p>\/* Get the unicode string length. *\/<br \/>unicode_string_length = (ULONG) *storage_pointer ;<\/p>\n<p>\/* Copy that string into the storage volume label field. *\/<br \/>_ux_utility_memory_copy(storage -&gt; ux_host_class_pima_storage_volume_label, storage_pointer, unicode_string_length); \/* Use case of memcpy is verified. *\/ \/\/ VULN: unchecked copy size for a copy in a fixed size (256 bytes) buffer (UX_HOST_CLASS_PIMA_STORAGE_MAX_LENGTH used to dynamically allocate storage_buffer is 512 bytes)<\/p>\n<p>}<\/p>\n<p>\/* Free the original storage info buffer. *\/<br \/>_ux_utility_memory_free(storage_buffer);<\/p>\n<p>\/* Return completion status. *\/<br \/>return(status);<br \/>}<br \/>&#8220;`<\/p>\n<p>&#8211;[ 4 &#8211; Affected products<\/p>\n<p>Eclipse ThreadX before version 6.4.0 was affected by the vulnerabilities<br \/>discussed in this advisory. The other bugs in Eclipse ThreadX NetX Duo and USBX<br \/>that we reported will be patched in subsequent releases of Eclipse ThreadX.<\/p>\n<p>&#8211;[ 5 &#8211; Remediation<\/p>\n<p>Eclipse ThreadX maintainers have fixed all vulnerabilities discussed in this<br \/>advisory.<\/p>\n<p>Please check the official Eclipse ThreadX channels for further information<br \/>about fixes.<\/p>\n<p>&#8211;[ 6 &#8211; Disclosure timeline<\/p>\n<p>We reported the vulnerabilities discussed in this advisory to Microsoft in<br \/>December 2023 and early January 2024, via their MSRC Researcher Portal [8].<br \/>For our efforts, we were awarded 7th place in the Top MSRC 2023 Q4 Azure<br \/>Security Researchers Leaderboard [9].<\/p>\n<p>Following the project ownership transfer to the Eclipse Foundation, with<br \/>Microsoft&#8217;s help, we coordinated with the new maintainers to provide<br \/>vulnerability information and fixes to the ThreadX users&#8217; community.<\/p>\n<p>The (simplified) coordinated disclosure timeline follows:<\/p>\n<p>2023-12-01: Reported two vulnerabilities to MSRC.<br \/>2023-12-13: MSRC confirmed our first vulnerability.<br \/>2023-12-14: MSRC confirmed our second vulnerability.<br \/>2023-12-21: Reported other two vulnerabilities to MSRC.<br \/>2023-12-31: Reported another vulnerability to MSRC.<br \/>2024-01-02: Reported other three vulnerabilities to MSRC.<br \/>2024-01-05: MSRC confirmed a vulnerability was fixed in version 6.4.<br \/>2024-01-06: MSRC informed us we made the 2023 Q4 leaderboard!<br \/>2024-01-10: MSRC confirmed another vulnerability was fixed in version 6.4.<br \/>2024-02-10: Asked MSRC for updates on all open reports.<br \/>2024-02-16: Asked the Eclipse Foundation for advice on how to proceed.<br \/>2024-02-20: Eclipse replied they were coordinating with MSRC.<br \/>2024-02-21: MSRC informed us of the ownership transfer to Eclipse.<br \/>2024-02-27: MSRC confirmed a third vulnerability was fixed in version 6.4.<br \/>2024-02-28: Upon MSRC&#8217;s request, we submitted our reports to Eclipse.<br \/>2024-03-05: Eclipse started creating GitHub advisories for all reports.<br \/>2024-03-13: Provided Eclipse with clarifications on some of the reports.<br \/>2024-03-15: MSRC provided some additional feedback on the transition.<br \/>2024-03-18: Eclipse finished creating GitHub advisories for all reports.<br \/>2024-03-22: MSRC closed the remaining cases after the transition.<br \/>2024-03-25: Eclipse published CVE-2024-2212, CVE-2024-2214, CVE-2024-2452.<br \/>2024-03-29: Provided Eclipse with clarifications on remaining reports.<br \/>2024-04-24: Asked for a status update on the remaining reports.<br \/>2024-04-26: Agreed to declass the remaining reports to standard issues.<br \/>2024-05-02: Sent draft advisory and writeup to MSRC and Eclipse.<br \/>2024-05-28: Published advisory and writeup.<\/p>\n<p>&#8211;[ 7 &#8211; Acknowledgments<\/p>\n<p>We would like to thank MSRC and the Eclipse Foundation (with a special mention<br \/>to Marta Rybczynska who took care of coordinated disclosure after the project<br \/>ownership change) for triaging and fixing the reported vulnerabilities. It was<br \/>a pleasure to work with you!<\/p>\n<p>&#8211;[ 8 &#8211; References<\/p>\n[1] https:\/\/eclipse-foundation.blog\/2023\/11\/21\/introducing-eclipse-threadx\/<br \/>[2] https:\/\/github.com\/eclipse-threadx\/<br \/>[3] https:\/\/security.humanativaspa.it\/ost2-zephyr-rtos-and-a-bunch-of-cves\/<br \/>[4] https:\/\/security.humanativaspa.it\/multiple-vulnerabilities-in-rt-thread-rtos\/<br \/>[5] https:\/\/security.humanativaspa.it\/multiple-vulnerabilities-in-riot-os\/<br \/>[6] https:\/\/security.humanativaspa.it\/big-update-to-my-semgrep-c-cpp-ruleset\/<br \/>[7] https:\/\/security.humanativaspa.it\/a-collection-of-weggli-patterns-for-c-cpp-vulnerability-research\/<br \/>[8] https:\/\/msrc.microsoft.com\/report\/vulnerability<br \/>[9] https:\/\/msrc.microsoft.com\/blog\/2024\/01\/congratulations-to-the-top-msrc-2023-q4-security-researchers\/<\/p>\n<p>Copyright (c) 2024 Marco Ivaldi and Humanativa Group. All rights reserved.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8211;[ HNS-2024-06 &#8211; HN Security Advisory &#8211; https:\/\/security.humanativaspa.it\/ * Title: Multiple vulnerabilities in Eclipse ThreadX* OS: Eclipse ThreadX &lt; 6.4.0* Author: Marco Ivaldi &lt;marco.ivaldi@hnsecurity.it&gt;* Date: 2024-05-28* CVE IDs and severity:* CVE-2024-2214 &#8211; High &#8211; 7.0 &#8211; CVSS:3.1\/AV:L\/AC:H\/PR:N\/UI:R\/S:U\/C:H\/I:H\/A:H* CVE-2024-2212 &#8211; High &#8211; 7.3 &#8211; CVSS:3.1\/AV:L\/AC:L\/PR:N\/UI:R\/S:U\/C:H\/I:H\/A:L* CVE-2024-2452 &#8211; High &#8211; 7.0 &#8211; CVSS:3.1\/AV:N\/AC:H\/PR:N\/UI:N\/S:U\/C:L\/I:H\/A:L* Advisory URLs: * https:\/\/github.com\/eclipse-threadx\/threadx\/security\/advisories\/GHSA-vmp6-qhp9-r66x* &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-57097","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/57097","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=57097"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/57097\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=57097"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=57097"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=57097"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}