mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-10-15 10:07:22 +00:00
fix(nimble): Avoid NULL proc dereference in GATT client procedures
GATT client APIs jumped to their common done label when proc allocation failed and passed a NULL proc to ble_gattc_process_status(), which dereferenced it and crashed with LoadProhibited. Return early on allocation failure after releasing caller owned mbufs and updating the failure statistics, and guard ble_gattc_process_status() against a NULL proc.
This commit is contained in:
+43
-30
@@ -1023,6 +1023,11 @@ ble_gattc_proc_set_resume_timer(struct ble_gattc_proc *proc)
|
||||
static void
|
||||
ble_gattc_process_status(struct ble_gattc_proc *proc, int status, bool insert_head)
|
||||
{
|
||||
/* Alloc-fail paths historically reached here with proc == NULL. */
|
||||
if (proc == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
if (!(proc->flags & BLE_GATTC_PROC_F_STALLED)) {
|
||||
@@ -1832,8 +1837,8 @@ ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg)
|
||||
if (proc == NULL) {
|
||||
BLE_HS_LOG(INFO, "GATTC proc alloc failed; conn_handle=0x%04x op=mtu\n",
|
||||
conn_handle);
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, mtu_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
proc->op = BLE_GATT_OP_MTU;
|
||||
@@ -2066,8 +2071,8 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb,
|
||||
if (proc == NULL) {
|
||||
BLE_HS_LOG(INFO, "GATTC proc alloc failed; "
|
||||
"conn_handle=0x%04x op=disc_all_svcs\n", conn_handle);
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, disc_all_svcs_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_SVCS);
|
||||
@@ -2300,8 +2305,8 @@ ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, disc_svc_uuid_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_SVC_UUID);
|
||||
@@ -2667,8 +2672,8 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, find_inc_svcs_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_FIND_INC_SVCS);
|
||||
@@ -2927,8 +2932,8 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, disc_all_chrs_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_CHRS);
|
||||
@@ -3194,8 +3199,8 @@ ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, disc_chrs_uuid_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_CHR_UUID);
|
||||
@@ -3430,8 +3435,8 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle,
|
||||
if (proc == NULL) {
|
||||
BLE_HS_LOG(INFO, "GATTC proc alloc failed; "
|
||||
"conn_handle=0x%04x op=disc_all_dscs\n", conn_handle);
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, disc_all_dscs_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_DSCS);
|
||||
@@ -4029,8 +4034,8 @@ ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle,
|
||||
if (proc == NULL) {
|
||||
BLE_HS_LOG(INFO, "GATTC proc alloc failed; "
|
||||
"conn_handle=0x%04x op=read\n", conn_handle);
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, read_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ);
|
||||
@@ -4196,8 +4201,8 @@ ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, read_uuid_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_UUID);
|
||||
@@ -4413,8 +4418,8 @@ ble_gattc_read_long(uint16_t conn_handle, uint16_t handle, uint16_t offset,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, read_long_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_LONG);
|
||||
@@ -4688,8 +4693,8 @@ ble_gattc_read_mult_internal(uint16_t conn_handle, const uint16_t *handles,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, read_mult_fail);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle,
|
||||
@@ -4950,8 +4955,9 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle,
|
||||
BLE_HS_LOG(INFO, "GATTC proc alloc failed; "
|
||||
"conn_handle=0x%04x op=write attr=0x%04x\n",
|
||||
conn_handle, attr_handle);
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, write_fail);
|
||||
os_mbuf_free_chain(txom);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE);
|
||||
@@ -5278,8 +5284,9 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, write_long_fail);
|
||||
os_mbuf_free_chain(txom);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE_LONG);
|
||||
@@ -5586,8 +5593,12 @@ ble_gattc_write_reliable(uint16_t conn_handle,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, write_reliable_fail);
|
||||
for (i = 0; i < num_attrs; i++) {
|
||||
os_mbuf_free_chain(attrs[i].om);
|
||||
attrs[i].om = NULL;
|
||||
}
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE_RELIABLE);
|
||||
@@ -6303,8 +6314,10 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle,
|
||||
|
||||
proc = ble_gattc_proc_alloc();
|
||||
if (proc == NULL) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
goto done;
|
||||
STATS_INC(ble_gattc_stats, indicate_fail);
|
||||
ble_gap_notify_tx_event(BLE_HS_ENOMEM, conn_handle, chr_val_handle, 1);
|
||||
os_mbuf_free_chain(txom);
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_INDICATE);
|
||||
|
||||
Reference in New Issue
Block a user