Knowledge · Findings record
A Keil build, read end to end
A public Keil build for a Cortex-M4: which components are inside and where the file shows it, which reported vulnerability has code in the build, which hardening is missing. With the commands that let you check it yourself.
- File
- ble_freertos_amota.axf
- Size
- 2,503,136 bytes
- Format
- ELF32 · ARM · EABI 5
- Target
- Apollo3 · Cortex-M4
- Analysed
- 19 October 2026 · app.legacymind.de
- SHA-256
- f33f7663bbd8b3fb4da733c57b008e439265ac688438b5c637da3c890e19fd13
0Result
- 2of 6reported vulnerabilities have code in the buildFreeRTOS 10.4.3 closes both, FreeRTOS 11.3.1 all 6.
- 3protection mechanisms are missingStack canary, MPU, Privilege separation.
- 3components without a version in the imageArm Cordio BLE stack, micro-ecc, Ambiq HAL: without a version, no match against known vulnerabilities.
1Components
Annex I, Part II, point (1)
Six components, three of them with a version in the file. Each row gives the file offset of the string that evidences it.
FreeRTOS
RTOS kernel
10.1.1
0x1fe9c · .debug_info, only in the AXF
../../../../../third_party/FreeRTOSv10.1.1/Source/timers.cArm Cordio BLE stack
Bluetooth stack, in LegacyMind as exactle
no evidence
0x17f3c · FLASH, also in the BIN
../../../../../third_party/exactle/wsf/sources/port/freertos/wsf_trace.cProject file: third_party/exactle; Arm Cordio r19.02 according to the SDK readme (cordio_profile_readme.md:14). The image carries no version.
micro-ecc
crypto library, in LegacyMind as uecc
no evidence
0x4cd18 · .debug_info, only in the AXF
../../../../../third_party/uecc/uECC.hProject file: third_party/uecc. The SDK names no version.
Ambiq HAL
vendor driver, in LegacyMind as hal_ambiq
no evidence
0x2e14 · FLASH, also in the BIN
ERROR_CHECK_VOID am_hal_ble_initialize(0, &BLE)Project file: mcu/apollo3; AmbiqSuite 2.4.2 according to VERSION.txt. The image carries no version.
Arm C library (armlib)
runtime library, in LegacyMind as Arm C library (armlib)
5.06 update 6 (build 750)
0x1dbd5b · .comment, only in the AXF
C:\Keil_v5\ARM\ARMCC\Bin\..\lib\armlib\c_w.lArm Compiler
toolchain
5.06
0x1fed7 · .debug_info, only in the AXF
Component: ARM Compiler 5.06 update 6 (build 750) Tool: ArmCC [4d3637]
2Vulnerabilities
Annex I, Part I, point (2)(a)
The analysis reports six CVEs in FreeRTOS 10.1.1. The symbol table of the same file says for which of them the affected code is linked: for two, not for four.
Code in the build · 2
- CVE-2021-31571
CVSS 9.8 · Critical
Integer overflow in queue.c when a queue is created.
Fixed in FreeRTOS 10.4.3
Symbol addressxQueueGenericCreate 0x1fe85
- CVE-2021-32020
CVSS 9.8 · Critical
Insufficient bounds checking in the kernel's heap management.
Fixed in FreeRTOS 10.4.3
Symbol addresspvPortMalloc 0x1bfb5
Code not in the build · 4
- CVE-2021-31572
CVSS 9.8 · Critical
Integer overflow in stream_buffer.c when a stream buffer is created.
Fixed in FreeRTOS 10.4.3
The build contains no stream buffer: no
StreamBufferfunction in the symbol table. - CVE-2024-28115
CVSS 8.8 · High
Insufficient protection against privilege escalation on MPU ports, if another vulnerability injects code.
Fixed in FreeRTOS 10.6.2
Affects MPU ports only. The build uses the port
portable/Keil/AMapollo2and contains noMPU_symbol. - CVE-2026-77234
CVSS 8.8 · High
Missing input validation lets an unprivileged task run code in kernel context on MPU ports.
Fixed in FreeRTOS 11.3.1
Affects MPU ports only. The build uses the port
portable/Keil/AMapollo2and contains noMPU_symbol. - CVE-2026-77237
CVSS 6.5 · Medium
Missing type check in xQueueAddToSet() lets an unprivileged task read kernel memory on MPU ports.
Fixed in FreeRTOS 11.3.1
Affects MPU ports only. The build uses the port
portable/Keil/AMapollo2and contains noMPU_symbol.
No match · 3
- Arm Cordio BLE stackWithout a version in the image, no match against known vulnerabilities.
- micro-eccWithout a version in the image, no match against known vulnerabilities.
- Ambiq HALWithout a version in the image, no match against known vulnerabilities.
We ran the symbol-table check for this record with nm; the report currently matches all six on the version alone. CVSS as in the report, fixed version according to the NVD, none of the six in the CISA KEV catalogue.
3Hardening
Annex I, Part I, point (2)(k)
Measured the way a microcontroller is measured: RELRO, NX and PIE do not exist on a Cortex-M.
Stack canary
missing
Evidence
No
__stack_chk_guard, no__stack_chk_failin the symbol table.What turns it on
Compile with
--protect_stack(Arm Compiler 5), or with-fstack-protector-strongon armclang.MPU
missing
Evidence
No
MPU_symbol; the build uses the portportable/Keil/AMapollo2.0x20e04 · .debug_info, only in the AXF
../../../../../third_party/FreeRTOSv10.1.1/Source/portable/Keil/AMapollo2/portmacro.hWhat turns it on
Use the FreeRTOS MPU port for Cortex-M4 and define the tasks' memory regions.
Privilege separation
missing
Evidence
Without the MPU port every task runs privileged; no
xPortRaisePrivilegein the symbol table.What turns it on
With the MPU port, create unprivileged tasks (
xTaskCreateRestricted).
4SBOM
Annex I, Part II, point (1)
The SBOM as CycloneDX 1.6, exactly as it comes out of the app.
5Verify
Three commands repeat the record on the file from the source above: the checksum, the file offsets with strings, the symbol addresses with nm. Above them, the sections of the file, so every offset has its place.
| Section | Offset | Size | in the BIN |
|---|---|---|---|
| FLASH | 0x34 | 0x17fb8 | yes |
| SRAM | 0x17fec | 0x954 | yes |
| .debug_abbrev | 0x18940 | 0x5c4 | no |
| .debug_frame | 0x18f04 | 0x6f8c | no |
| .debug_info | 0x1fe90 | 0xe68fc | no |
| .debug_line | 0x10678c | 0x366e4 | no |
| .debug_loc | 0x13ce70 | 0x15a40 | no |
| .debug_macinfo | 0x1528b0 | 0x60590 | no |
| .debug_pubnames | 0x1b2e40 | 0x8122 | no |
| .symtab | 0x1baf64 | 0x10f40 | no |
| .strtab | 0x1cbea4 | 0xfd20 | no |
| .note | 0x1dbbc4 | 0x1c | no |
| .comment | 0x1dbbe0 | 0x872cc | no |
| .shstrtab | 0x262eac | 0x94 | no |
sha256sum ble_freertos_amota.axfAusgabe
f33f7663bbd8b3fb4da733c57b008e439265ac688438b5c637da3c890e19fd13 ble_freertos_amota.axffor s in "FreeRTOSv10.1.1" "third_party/exactle/" "third_party/uecc/" \
"am_hal_ble_initialize" "armlib\\c_w.l" "Component: ARM Compiler 5.06"; \
do strings -a -t x ble_freertos_amota.axf | grep -m1 -F "$s"; doneAusgabe
1fe9c../ ../ ../ ../ ../ third_party/ FreeRTOSv10.1.1/ Source/ timers.c17f3c../ ../ ../ ../ ../ third_party/ exactle/ wsf/ sources/ port/ freertos/ wsf_trace.c4cd18../ ../ ../ ../ ../ third_party/ uecc/ uECC.h2e14ERROR_CHECK_VOID am_hal_ble_initialize(0, &BLE)1dbd5bC:\ Keil_v5\ ARM\ ARMCC\ Bin\ ..\ lib\ armlib\ c_w.l1fed7Component: ARM Compiler 5.06 update 6 (build 750) Tool: ArmCC [4d3637]nm ble_freertos_amota.axf \
| grep -E "xQueueGenericCreate|pvPortMalloc|StreamBuffer|MPU_|__stack_chk|xPortRaisePrivilege|xTaskCreateRestricted"Ausgabe
0001bfb5T pvPortMalloc0001fe85T xQueueGenericCreateRun with GNU nm (GNU Binutils for Ubuntu) 2.42 and GNU strings on the file with the SHA-256 above, on 20 October 2026.
Questions about the record
- Why do three components have no version?
- For Arm Cordio BLE stack, micro-ecc and Ambiq HAL the file holds source paths and assert strings, but no version number. The record leaves the field blank instead of taking a version from the SDK.
- Why only vulnerabilities in FreeRTOS?
- Only what carries a version can be matched. For the compiler and the runtime library, the analysis reports no known vulnerabilities in these versions; the three libraries without a version stay unmatched.
- Which file should we upload, the AXF or the BIN?
- The AXF, ELF or OUT of the build. In this record, FreeRTOS 10.1.1, Arm C library 5.06 update 6 (build 750) and Arm Compiler 5.06 appear only in sections that are not copied into the BIN (.debug_info, .comment); a BIN on its own yields only what its own bytes evidence. Upload both from the same build, and the BIN gets the components of the AXF.
- What does the file tell you about the toolchain?
- The `.comment` section names ARM Compiler 5.06 update 6 (build 750), the linker command line and five libraries of the Arm C runtime: c_w.l, fz_wm.l, h_w.l, m_wm.l and vfpsupport.l. The compiler invocations also show the Device Family Pack Apollo_DFP 1.1.3 in the include path. The project file names 1.1.0; the build used 1.1.3.
- Why is a function from the source code missing from the build?
- Because armlink removes unused sections by default, and this build puts every function in its own section. `vTaskEndScheduler` is in tasks.c at line 2061; the symbol table does not have it. That is why the record checks, for every CVE, whether the affected code is linked.
- Is there a map file for this build?
- The linker ran with `--map` and `--list=.\Listings\ble_freertos_amota.map`; the AXF says so. The Listings folder is not published in the repository. In your own build, the same line in the AXF shows whether the linker wrote a map file, and where. With `--info=sizes` the map file lists code and data per object and per library member.
- Do you need our source code or our build system?
- No. The analysis runs on the file your build produces, or on the image your customer receives. No repository, no access to your toolchain, no access to the device.
- What does this mean for the reporting obligation under CRA Art. 14?
- None of the 6 reported vulnerabilities is in the CISA KEV catalogue of actively exploited vulnerabilities. If one of them is exploited, the first question within the 24-hour deadline is which shipped products contain FreeRTOS 10.1.1. With an SBOM per release, that is one search. You file the report yourself.
The same review for your build
In the free CRA readiness check we analyse one file from your build. You get the report and the SBOM within three working days.