flipperzero-firmware
flipperzero-firmware copied to clipboard
Furi: Detect use-after-free
What's new
free()now marks memory with0xDDBusFaulthandler checks for0xDDDDDDDDand 64K after it to determine "Possible use-after-free"- if such memory address is not dereferenced no crash will happen, but this change is still useful while debugging, as seeing 0xDD in your data is a clear giveaway of use-after-free
- added back
BusFaulthandler extra logging from old TLSF experiment - fixed atomicity in
furi_semaphore_release():- if thread A is waiting for acquire() and thread B calls release()
- then halfway through release() code, A would wake up and continue, before B finishes release()
- this could cause use-after-free if A free()s semaphore after acquire(), because after this B would finish release() which dereferences instance->event_loop_link
- for example, RpcCli had this use-after-free:
rpc_cli_command_start_session()is waiting forfuri_semaphore_acquire()rpc_cli_session_terminated_callback()willfuri_semaphore_release()- this wakes up
rpc_cli_command_start_session()which then does furi_semaphore_free() - later,
furi_semaphore_release()inside ofrpc_cli_session_terminated_callback()resumes, and dereferences the semaphore thatrpc_cli_command_start_session()has already free'd
- there might be more similar issues with event loop items being used after yielding, which would break atomicity and lead to possible use-after-free, but i have not looked for them or found other crashes like this yet
Verification
- test anything and everything for hidden use-after-free that were unknown until now
Checklist (For Reviewer)
- [ ] PR has description of feature/bug or link to Confluence/Jira task
- [ ] Description contains actions to verify feature/bugfix
- [ ] I've built this code, uploaded it to the device and verified feature/bugfix
BusFaulthandler checks for0xDDDDDDDDand 64K after it to determine "Possible use-after-free"
Just sanity checking - is nothing mapped there in the Cortex M4 memory map? Peripheral or something?
BusFaulthandler checks for0xDDDDDDDDand 64K after it to determine "Possible use-after-free"Just sanity checking - is nothing mapped there in the Cortex M4 memory map? Peripheral or something?
doesnt seem like it from what i can see, in firmware code i see
/*!< Boundary memory map */
#define FLASH_BASE (0x08000000UL)/*!< FLASH(up to 1 MB) base address */
#define SRAM_BASE (0x20000000UL)/*!< SRAM(up to 256 KB) base address */
#define PERIPH_BASE (0x40000000UL)/*!< Peripheral base address */
/*!< Memory, OTP and Option bytes */
/* Base addresses */
#define SYSTEM_MEMORY_BASE (0x1FFF0000UL) /*!< System Memory : 28Kb (0x1FFF0000 - 0x1FFF6FFF) */
#define OTP_AREA_BASE (0x1FFF7000UL) /*!< OTP area : 1kB (0x1FFF7000 - 0x1FFF73FF) */
#define OPTION_BYTE_BASE (0x1FFF8000UL) /*!< Option Bytes : 4kB (0x1FFF8000 - 0x1FFF8FFF) */
#define ENGI_BYTE_BASE (0x1FFF7400UL) /*!< Engi Bytes : 3kB (0x1FFF7400 - 0x1FFF7FFF) */
however in the ARM documentation, it seems like 0xDDDDDDDD would fall into the "external device" region. not sure what that means
https://developer.arm.com/documentation/ddi0439/b/Programmers-Model/System-address-map
Double edge sword: on the one side it will do what you expect it to do when we talk about pointers, but then if it is value then it will cause more damage. I wish there were some statistics to choose better option.
Btw, do you mind to split SCB flags+semaphore fix into separate PR, so I can fast track it?