A missing check for the existence of a channel corresponding to a user-supplied channel ID may lead to a near-null value to be treated as a channel object, leading to DoS (or possibly even RCE on some embedded systems).
Proposed Security Advisory Text:
# Impact
While processing the L2CAP protocol, the Bluetooth Low Energy stack of Contiki-NG maps an incoming channel id to its metadata structure. In this structure, state information such as flow control metadata such as credits are maintained in input_l2cap_credit (os/net/mac/ble/ble-l2cap.c).
However, in function input_l2cap_credit, it is not checked that the metadata corresponding to the user-supplied channel id actually exists. This leads to the use of a NULL pointer which results in a crash or corruption of memory.
In input_l2cap_credit, it is assumed that for an incoming L2CAP_CODE_CREDIT packet that a channel exists for the sending address.
Code path:
- ble
input
function callsinput_l2cap_frame_signal_channel
: https://github.com/contiki-ng/contiki-ng/blob/release/v4.8/os/net/mac/ble/ble-l2cap.c#L482 ->input_l2cap_frame_signal_channel
callsinput_l2cap_credit
A check for this condition within the same ble input
function can be found in a different place here:
Crash reason:
- Use of channel object without NULL pointer check:
channel->channel_peer.credits += credits;
- Link: https://github.com/contiki-ng/contiki-ng/blob/release/v4.8/os/net/mac/ble/ble-l2cap.c#L393
A crafted packet reaching the L2CAP_SIGNAL_CHANNEL
can lead to a write to a location near address 0. Depending on the target, the zero address may or not be mapped. If zero is mapped and writable, an arbitrary addition is performed (which might impact an interrupt vector address for zero-based firmware images). An attacker might be able to use such an interrupt service routine write to hijack control flow (RCE). If it is not mapped, the firmware will crash, resulting in a denial of service (DoS).
This issue could be fixed by inserting a check for the channel being NULL:
diff --git a/os/net/mac/ble/ble-l2cap.c b/os/net/mac/ble/ble-l2cap.c
index fb755cc85..36d8443bc 100644
--- a/os/net/mac/ble/ble-l2cap.c
+++ b/os/net/mac/ble/ble-l2cap.c
@@ -378,6 +378,11 @@ input_l2cap_credit(uint8_t *data)
uint16_t credits;
l2cap_channel_t *channel = get_channel_for_addr(packetbuf_addr(PACKETBUF_ADDR_SENDER));
+ if(channel == NULL) {
+ LOG_WARN("process_l2cap_credit: no channel found for sender address\n");
+ return;
+ }
+
/* uint8_t identifier = data[0]; */
memcpy(&len, &data[1], 2);