Browse Source

merkle_sync: ms_outq_drain_cb — сохранять e->len до etcp_send (UAF); документировать ownership etcp_send

v2
evgeny 3 weeks ago
parent
commit
da329d0479
  1. 3
      src/chat/merkle_sync.c
  2. 7
      src/transport_layer/etcp_api.h

3
src/chat/merkle_sync.c

@ -316,10 +316,11 @@ static void ms_outq_drain_cb(struct ll_queue* q, void* arg) {
if (e->dgram) u_free(e->dgram); if (e->dgram) u_free(e->dgram);
queue_entry_free(e); queue_entry_free(e);
} else { } else {
uint16_t len = e->len; /* etcp_send может синхронно освободить e (ownership переходит в очередь) */
int r = etcp_send(conn, e); int r = etcp_send(conn, e);
if (r != 0) { if (e->dgram) u_free(e->dgram); queue_entry_free(e); } if (r != 0) { if (e->dgram) u_free(e->dgram); queue_entry_free(e); }
DEBUG_DEBUG(DEBUG_CATEGORY_MEMBER_SYNC, "%s: outq drain peer=%016llx len=%u rc=%d left=%d", DEBUG_DEBUG(DEBUG_CATEGORY_MEMBER_SYNC, "%s: outq drain peer=%016llx len=%u rc=%d left=%d",
MS_ID, (unsigned long long)s->peer, e->len, r, queue_entry_count(s->out_q)); MS_ID, (unsigned long long)s->peer, len, r, queue_entry_count(s->out_q));
} }
if (queue_entry_count(s->out_q) > 0 && conn && conn->send_input_q) if (queue_entry_count(s->out_q) > 0 && conn && conn->send_input_q)
queue_waiter_wait(conn->send_input_q, &s->waiter, ms_outq_drain_cb, s); queue_waiter_wait(conn->send_input_q, &s->waiter, ms_outq_drain_cb, s);

7
src/transport_layer/etcp_api.h

@ -162,8 +162,11 @@ struct ETCP_BINDINGS {
* @param entry Элемент очереди с данными для отправки * @param entry Элемент очереди с данными для отправки
* @return 0 при успехе, -1 при ошибке * @return 0 при успехе, -1 при ошибке
* *
* @note Функция забирает ownership entry - вызывающий код не должен * @note Функция забирает ownership entry — вызывающий код не должен
* освобождать entry после вызова * ни освобождать, ни читать entry после вызова: если очередь
* normalizer'а пуста, entry освобождается СИНХРОННО внутри этого
* вызова (queue_data_put → callback → queue_entry_free). Любые
* нужные поля entry надо сохранять до etcp_send().
*/ */
int etcp_send(struct ETCP_CONN* conn, struct ll_entry* entry); int etcp_send(struct ETCP_CONN* conn, struct ll_entry* entry);

Loading…
Cancel
Save