BusFault handler checks for 0xDDDDDDDD and 64K after it to determine "Possible use-after-free"
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 for furi_semaphore_acquire()
rpc_cli_session_terminated_callback() will furi_semaphore_release()
this wakes up rpc_cli_command_start_session() which then does furi_semaphore_free()
later, furi_semaphore_release() inside of rpc_cli_session_terminated_callback() resumes, and dereferences the semaphore that rpc_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
For the reviewer
[ ] I've uploaded the firmware with this patch to a device and verified its functionality
[ ] I've confirmed the bug to be fixed / feature to be stable
What's new
free()
now marks memory with0xDD
BusFault
handler checks for0xDDDDDDDD
and 64K after it to determine "Possible use-after-free"furi_semaphore_release()
:rpc_cli_command_start_session()
is waiting forfuri_semaphore_acquire()
rpc_cli_session_terminated_callback()
willfuri_semaphore_release()
rpc_cli_command_start_session()
which then does furi_semaphore_free()furi_semaphore_release()
inside ofrpc_cli_session_terminated_callback()
resumes, and dereferences the semaphore thatrpc_cli_command_start_session()
has already free'dFor the reviewer