Double free in `ble_hci_emspi_rx_acl()` on host ACL delivery failure
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- c
- Domain
- embedded-iot
Research direction
Start in nimble/transport/emspi/src/ble_hci_emspi.c at ble_hci_emspi_rx_acl(), then read ble_transport_to_hs_acl_impl() in nimble/host/src/ble_hs.c and the ownership comment in ble_hs_rx_data(). Trace the ble_mqueue_put() failure path and verify that a host delivery failure consumes the mbuf only once, while earlier receive failures retain their existing cleanup.
Written by the indexing model from the issue text.
Description
I found a possible double free in the EMSPI HCI transport receive path when an incoming ACL packet is passed to the host and host-side queuing fails.
File: nimble/transport/emspi/src/ble_hci_emspi.c
Function: ble_hci_emspi_rx_acl
Relevant code:
om = ble_transport_alloc_acl_from_ll();
assert(om != NULL);
rc = ble_hci_emspi_rx(om->om_data, BLE_HCI_DATA_HDR_SZ);
if (rc != 0) {
goto err;
}
...
rc = ble_transport_to_hs_acl(om);
if (rc != 0) {
goto err;
}
return 0;
err:
os_mbuf_free_chain(om);
return rc;
The error label is correct for failures that occur before ownership is passed
to the host. However, ble_transport_to_hs_acl() eventually calls the host
implementation:
File: nimble/host/src/ble_hs.c
ble_transport_to_hs_acl_impl(struct os_mbuf *om)
{
return ble_hs_rx_data(om, NULL);
}
ble_hs_rx_data() documents and implements that it consumes the mbuf regardless
of the outcome:
/* Called when a data packet is received from the controller. This function
* consumes the supplied mbuf, regardless of the outcome.
*/
static int
ble_hs_rx_data(struct os_mbuf *om, void *arg)
{
...
rc = ble_mqueue_put(&ble_hs_rx_q, ble_hs_evq, om);
if (rc != 0) {
os_mbuf_free_chain(om);
return BLE_HS_EOS;
}
return 0;
}
So when ble_mqueue_put() fails, ble_hs_rx_data() already frees om and
returns an error. ble_hci_emspi_rx_acl() then sees the non-zero return value,
jumps to err, and frees the same mbuf again.
This can happen under low-memory or queue-allocation failure conditions in the
host receive path.
Suggested fix: after calling ble_transport_to_hs_acl(om), do not free om on
failure because ownership has already been transferred. One option is to return
the error directly:
rc = ble_transport_to_hs_acl(om);
if (rc != 0) {
return rc;
}
- Dominant language
- C
- Stars
- 892
- Forks
- 512
- Avg merge
- 6d 1h
- Merged PRs (30d)
- 4
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from apache/mynewt-nimble
-
apache/mynewt-nimble#2283 · 1 assignee ·
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
apache/mynewt-nimble#2279 ·
-
Difficulty 5/5 Over a week Newbie friendliness 45/100
apache/mynewt-nimble#2278 ·
-
Event driven mechanism to notify applications when MSYS capacity recovers after allocation failure Open
Difficulty 5/5 Over a week Newbie friendliness 38/100
apache/mynewt-nimble#2274 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 52/100
apache/mynewt-nimble#2262 · 2 comments ·
All issues in apache/mynewt-nimble
Similar issues
-
level/task module/gcp type/bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
-
Difficulty 1/5 Under an hour Newbie friendliness 86/100
hapostgres/pg_auto_failover#1190 ·
-
docs
Difficulty 1/5 Under an hour Newbie friendliness 85/100
-
P3 sonic-vpp
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
sonic-net/sonic-buildimage#29662 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 94/100
spack/spack-packages#6586 ·