We have identified a new heap buffer overflow vulnerability in Samsung’s Android Radio Interface Layer implementation. The vulnerability can be exploited by a malicious (compromised) baseband runtime to achieve arbitrary code execution in Android in the radio context.
The vulnerability we are disclosing in this advisory affected a wide range of Samsung devices, including phones on the newest Exynos chipsets. The July 2023 issue of the Samsung Mobile Security Bulletin contains this vulnerability as CVE-2023-30646.
Vulnerability Details
The Exynos vendor RIL implementation, provided by the libsec-ril.so
library, exposes an Inter Process Call (IPC) interface to the baseband processor.
The baseband processor can use this API through dedicated IPC messages.
When the IpcProtocol41Sms::IpcRxCBConfig
IPC handler is triggered it allocates a heap objects
and calls BroadcastSmsConfig::BroadcastSmsConfig
to populate it based on the content of the IPC message.
The vulnerability is in this BroadcastSmsConfig::BroadcastSmsConfig
as it fails to verify the provided length field and overflows the allocated buffer.
The length is stored on a single bytes, the maximum value is 0xff while the heap buffer size is 0x1b0 bytes,
however it is iterated and written by four byte increments, allowing a 598 byte overflow.
BroadcastSmsConfig *
IpcProtocol41Sms::IpcRxCBConfig
(char *param_1,sipc_ipc_msg *ipc_msg,int *param_3,RegistrantType *param_4)
{
[...]
// [1] The object is allocated and the constructor is called with IPC message content
this = (BroadcastSmsConfig *)operator.new(0x1b0);
BroadcastSmsConfig::BroadcastSmsConfig
(this,(uint)(byte)ipc_msg->data[1],(uint)(byte)ipc_msg->data[2],
(uint)(byte)ipc_msg->data[3],data4,(ushort *)(ipc_msg->data + 5));
void __thiscall
BroadcastSmsConfig::BroadcastSmsConfig
(BroadcastSmsConfig *this,int data1,int data2,int data3,int data4,ushort *data_rest)
{
[...]
if (0 < data4) {
data4_len = (ulong)(uint)data4;
if (((uint)data4 < 8) ||
((this + 0x1c < data_rest + data4_len && (data_rest < this + data4_len * 4 + 0x1c)))) {
idx_dst = 0;
}
else {
idx_dst = data4_len & 0xfffffff8;
src = (undefined8 *)(data_rest + 4);
puVar2 = (ulong *)(this + 0x2c);
uVar3 = idx_dst;
// [2] The overflow is either triggered in this loop
do {
uVar4 = src[-1];
uVar5 = *src;
src = src + 2;
uVar3 = uVar3 - 8;
puVar2[-1] = (ulong)CONCAT24((short)((ulong)uVar4 >> 0x30),
(uint)(ushort)((ulong)uVar4 >> 0x20));
puVar2[-2] = (ulong)(CONCAT24((short)((ulong)uVar4 >> 0x10),(int)uVar4) & 0xffff0000ffff);
puVar2[1] = (ulong)CONCAT24((short)((ulong)uVar5 >> 0x30),
(uint)(ushort)((ulong)uVar5 >> 0x20));
*puVar2 = (ulong)(CONCAT24((short)((ulong)uVar5 >> 0x10),(int)uVar5) & 0xffff0000ffff);
puVar2 = puVar2 + 4;
} while (uVar3 != 0);
if (idx_dst == data4_len) {
return;
}
// [3] Or this loop
do {
/* the max possible value of data4_len is 255
allocation 0x1b0 size
we can write up to 0x1c + 4 * 0xff bytes */
*(uint *)(this + idx_dst * 4 + 0x1c) = (uint)data_rest[idx_dst];
idx_dst = idx_dst + 1;
} while (idx_dst < data4_len);
}
return;
}
The function allocates the heap object at [1] then BroadcastSmsConfig::BroadcastSmsConfig
uses the length field at [2] and [3]
to carry out the copy without further checks.
The baseband firmware has dedicated API functions for sending and receiving IPC messages.
These functions serialize the IPC content into the dedicated shared memory ring-buffers and signal the kernel through an interrupt.
On the AP processor side the CPIF Android kernel driver retrieves the IPC message content from the shared memory and exposes it to the user-space
through the /dev/umts_ipc0
and/or /dev/umts_ipc1
character devices.
Within the vendor rild implementation (libsec-ril.so
) there are dedicated threads for continuously polling these devices.
The entry point of the threads is IoChannelReader::Run
and they block on the device read in the IoChannel::Read
function.
Once an IPC message is read from the character device it is passed to IpcModem::ReceiveMessage
and subsequently to the IpcModem::DoIoChannelRouting
and IpcModem::DoIoChannelRoutingRx
functions.
The IpcModem::DoIoChannelRoutingRx
function receives the pointer to the appropriate IoChannel
object where the IPC message was retrieved.
IPC messages are passed to IpcModem::GetIpcMessage
and then forwarded to IpcModem::ProcessSingleIpcMessageReceived
where the appropriate IpcProtocol41*
implementation is retrieved based on the IPC command value.
Finally, the IpcProtocol41*::GetRxData
function is called which is responsible for calling the requested IPC API endpoint, based on the subcommand of the IPC message.
Affected Devices
All Samsung chipsets containing Samsung’s baseband implementation, including all Exynos chipsets.
Fix
Samsung OTA images, released after July 2023, contain the fix for the vulnerability.
Timeline
- 2023.04.01. Bug reported to Samsung PSIRT
- 2023.05.12. Samsung confirms vulnerability
- 2023.06.26. Samsung confirms fix will be released in the July security bulletin
- 2023.07.11. Samsung releases security bulletin
- 2023.09.26. TASZK informs Samsung of disclosure plan, Samsung confirms
- 2023.11.03. Vulnerability released at Hardwear.io
- 2023.11.26. Advisory release