mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 1.17.0
- [API Change] Packet out Memory Interface (PMI) update: - Split PMI pool return into pmi_release and pmi_return - PMI callbacks take peer_ctx and is_ipv6 arguments - [BUGFIX] Fix use-after-free when certificate is updated - Silence gcc warning in optimized mode by performing useless initialization - cmake: use the standard variable CMAKE_BUILD_TYPE instead of DEVEL_MODE
This commit is contained in:
parent
66f9afccd0
commit
1e75f9380e
15 changed files with 178 additions and 64 deletions
|
@ -6,6 +6,7 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -244,14 +245,14 @@ lsquic_engine_check_settings (const struct lsquic_engine_settings *settings,
|
|||
|
||||
|
||||
static void
|
||||
free_packet (void *ctx, unsigned char *packet_data)
|
||||
free_packet (void *ctx, void *conn_ctx, void *packet_data, char is_ipv6)
|
||||
{
|
||||
free(packet_data);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
malloc_buf (void *ctx, size_t size)
|
||||
malloc_buf (void *ctx, void *conn_ctx, unsigned short size, char is_ipv6)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
@ -259,7 +260,7 @@ malloc_buf (void *ctx, size_t size)
|
|||
|
||||
static const struct lsquic_packout_mem_if stock_pmi =
|
||||
{
|
||||
malloc_buf, (void(*)(void *, void *)) free_packet,
|
||||
malloc_buf, free_packet, free_packet,
|
||||
};
|
||||
|
||||
|
||||
|
@ -821,6 +822,13 @@ really_encrypt_packet (const lsquic_conn_t *conn,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
conn_peer_ipv6 (const struct lsquic_conn *conn)
|
||||
{
|
||||
return AF_INET6 == ((struct sockaddr *) conn->cn_peer_addr)->sa_family;
|
||||
}
|
||||
|
||||
|
||||
static enum { ENCPA_OK, ENCPA_NOMEM, ENCPA_BADCRYPT, }
|
||||
encrypt_packet (lsquic_engine_t *engine, const lsquic_conn_t *conn,
|
||||
lsquic_packet_out_t *packet_out)
|
||||
|
@ -829,10 +837,15 @@ encrypt_packet (lsquic_engine_t *engine, const lsquic_conn_t *conn,
|
|||
size_t bufsz;
|
||||
unsigned sent_sz;
|
||||
unsigned char *buf;
|
||||
int ipv6;
|
||||
|
||||
bufsz = conn->cn_pf->pf_packout_header_size(conn, packet_out->po_flags) +
|
||||
packet_out->po_data_sz + QUIC_PACKET_HASH_SZ;
|
||||
buf = engine->pub.enp_pmi->pmi_allocate(engine->pub.enp_pmi_ctx, bufsz);
|
||||
if (bufsz > USHRT_MAX)
|
||||
return ENCPA_BADCRYPT; /* To cause connection to close */
|
||||
ipv6 = conn_peer_ipv6(conn);
|
||||
buf = engine->pub.enp_pmi->pmi_allocate(engine->pub.enp_pmi_ctx,
|
||||
conn->cn_peer_ctx, bufsz, ipv6);
|
||||
if (!buf)
|
||||
{
|
||||
LSQ_DEBUG("could not allocate memory for outgoing packet of size %zd",
|
||||
|
@ -847,19 +860,51 @@ encrypt_packet (lsquic_engine_t *engine, const lsquic_conn_t *conn,
|
|||
|
||||
if (enc_sz < 0)
|
||||
{
|
||||
engine->pub.enp_pmi->pmi_release(engine->pub.enp_pmi_ctx, buf);
|
||||
engine->pub.enp_pmi->pmi_return(engine->pub.enp_pmi_ctx,
|
||||
conn->cn_peer_ctx, buf, ipv6);
|
||||
return ENCPA_BADCRYPT;
|
||||
}
|
||||
|
||||
packet_out->po_enc_data = buf;
|
||||
packet_out->po_enc_data_sz = enc_sz;
|
||||
packet_out->po_sent_sz = sent_sz;
|
||||
packet_out->po_flags |= PO_ENCRYPTED|PO_SENT_SZ;
|
||||
packet_out->po_flags &= ~PO_IPv6;
|
||||
packet_out->po_flags |= PO_ENCRYPTED|PO_SENT_SZ|(ipv6 << POIPv6_SHIFT);
|
||||
|
||||
return ENCPA_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
release_or_return_enc_data (struct lsquic_engine *engine,
|
||||
void (*pmi_rel_or_ret) (void *, void *, void *, char),
|
||||
struct lsquic_conn *conn, struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
pmi_rel_or_ret(engine->pub.enp_pmi_ctx, conn->cn_peer_ctx,
|
||||
packet_out->po_enc_data, lsquic_packet_out_ipv6(packet_out));
|
||||
packet_out->po_flags &= ~PO_ENCRYPTED;
|
||||
packet_out->po_enc_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
release_enc_data (struct lsquic_engine *engine, struct lsquic_conn *conn,
|
||||
struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
release_or_return_enc_data(engine, engine->pub.enp_pmi->pmi_release,
|
||||
conn, packet_out);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
return_enc_data (struct lsquic_engine *engine, struct lsquic_conn *conn,
|
||||
struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
release_or_return_enc_data(engine, engine->pub.enp_pmi->pmi_return,
|
||||
conn, packet_out);
|
||||
}
|
||||
|
||||
|
||||
STAILQ_HEAD(conns_stailq, lsquic_conn);
|
||||
TAILQ_HEAD(conns_tailq, lsquic_conn);
|
||||
|
||||
|
@ -1006,12 +1051,7 @@ send_batch (lsquic_engine_t *engine, struct conns_out_iter *conns_iter,
|
|||
* or until it times out and regenerated.
|
||||
*/
|
||||
if (batch->packets[i]->po_flags & PO_ENCRYPTED)
|
||||
{
|
||||
batch->packets[i]->po_flags &= ~PO_ENCRYPTED;
|
||||
engine->pub.enp_pmi->pmi_release(engine->pub.enp_pmi_ctx,
|
||||
batch->packets[i]->po_enc_data);
|
||||
batch->packets[i]->po_enc_data = NULL; /* JIC */
|
||||
}
|
||||
release_enc_data(engine, batch->conns[i], batch->packets[i]);
|
||||
}
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT))
|
||||
for ( ; i < (int) n_to_send; ++i)
|
||||
|
@ -1074,6 +1114,14 @@ send_packets_out (struct lsquic_engine *engine,
|
|||
coi_deactivate(&conns_iter, conn);
|
||||
continue;
|
||||
}
|
||||
if ((packet_out->po_flags & PO_ENCRYPTED)
|
||||
&& lsquic_packet_out_ipv6(packet_out) != conn_peer_ipv6(conn))
|
||||
{
|
||||
/* Peer address changed since the packet was encrypted. Need to
|
||||
* reallocate.
|
||||
*/
|
||||
return_enc_data(engine, conn, packet_out);
|
||||
}
|
||||
if (!(packet_out->po_flags & (PO_ENCRYPTED|PO_NOENCRYPT)))
|
||||
{
|
||||
switch (encrypt_packet(engine, conn, packet_out))
|
||||
|
|
|
@ -173,6 +173,7 @@ static void free_info (lsquic_session_cache_info_t *);
|
|||
/* client */
|
||||
static cert_hash_item_t *make_cert_hash_item(struct lsquic_str *domain, struct lsquic_str **certs, int count);
|
||||
static int c_insert_certs(cert_hash_item_t *item);
|
||||
static void c_erase_certs(struct lsquic_hash_elem *el);
|
||||
static void c_free_cert_hash_item (cert_hash_item_t *item);
|
||||
|
||||
static int get_tag_val_u32 (unsigned char *v, int len, uint32_t *val);
|
||||
|
@ -265,16 +266,23 @@ static int init_hs_hash_tables(int flags)
|
|||
|
||||
|
||||
/* client */
|
||||
cert_hash_item_t *
|
||||
c_find_certs (const lsquic_str_t *domain)
|
||||
struct lsquic_hash_elem *
|
||||
c_get_certs_elem (const lsquic_str_t *domain)
|
||||
{
|
||||
struct lsquic_hash_elem *el;
|
||||
|
||||
if (!s_cached_client_certs)
|
||||
return NULL;
|
||||
|
||||
el = lsquic_hash_find(s_cached_client_certs, lsquic_str_cstr(domain),
|
||||
return lsquic_hash_find(s_cached_client_certs, lsquic_str_cstr(domain),
|
||||
lsquic_str_len(domain));
|
||||
}
|
||||
|
||||
|
||||
/* client */
|
||||
cert_hash_item_t *
|
||||
c_find_certs (const lsquic_str_t *domain)
|
||||
{
|
||||
struct lsquic_hash_elem *el = c_get_certs_elem(domain);
|
||||
|
||||
if (el == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -335,6 +343,15 @@ c_insert_certs (cert_hash_item_t *item)
|
|||
}
|
||||
|
||||
|
||||
/* client */
|
||||
static void
|
||||
c_erase_certs (struct lsquic_hash_elem *el)
|
||||
{
|
||||
if (s_cached_client_certs && el)
|
||||
lsquic_hash_erase(s_cached_client_certs, el);
|
||||
}
|
||||
|
||||
|
||||
static int save_session_info_entry(lsquic_str_t *key, lsquic_session_cache_info_t *entry)
|
||||
{
|
||||
lsquic_str_setto(&entry->sni_key, lsquic_str_cstr(key), lsquic_str_len(key));
|
||||
|
@ -1364,7 +1381,11 @@ lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
|
|||
int ret;
|
||||
lsquic_session_cache_info_t *info = enc_session->info;
|
||||
hs_ctx_t * hs_ctx = &enc_session->hs_ctx;
|
||||
cert_hash_item_t *cached_certs_item = c_find_certs(&hs_ctx->sni);
|
||||
cert_hash_item_t *cached_certs_item = NULL;
|
||||
struct lsquic_hash_elem *el = c_get_certs_elem(&hs_ctx->sni);
|
||||
|
||||
if (el)
|
||||
cached_certs_item = lsquic_hashelem_getdata(el);
|
||||
|
||||
/* FIXME get the number first */
|
||||
lsquic_str_t **out_certs = NULL;
|
||||
|
@ -1427,6 +1448,8 @@ lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
|
|||
;
|
||||
else
|
||||
{
|
||||
if (el)
|
||||
c_erase_certs(el);
|
||||
if (cached_certs_item)
|
||||
c_free_cert_hash_item(cached_certs_item);
|
||||
|
||||
|
|
|
@ -279,7 +279,7 @@ lsquic_packet_out_new (struct lsquic_mm *mm, struct malo *malo, int use_cid,
|
|||
|
||||
void
|
||||
lsquic_packet_out_destroy (lsquic_packet_out_t *packet_out,
|
||||
struct lsquic_engine_public *enpub)
|
||||
struct lsquic_engine_public *enpub, void *peer_ctx)
|
||||
{
|
||||
if (packet_out->po_flags & PO_SREC_ARR)
|
||||
{
|
||||
|
@ -292,8 +292,8 @@ lsquic_packet_out_destroy (lsquic_packet_out_t *packet_out,
|
|||
}
|
||||
}
|
||||
if (packet_out->po_flags & PO_ENCRYPTED)
|
||||
enpub->enp_pmi->pmi_release(enpub->enp_pmi_ctx,
|
||||
packet_out->po_enc_data);
|
||||
enpub->enp_pmi->pmi_release(enpub->enp_pmi_ctx, peer_ctx,
|
||||
packet_out->po_enc_data, lsquic_packet_out_ipv6(packet_out));
|
||||
if (packet_out->po_nonce)
|
||||
free(packet_out->po_nonce);
|
||||
lsquic_mm_put_packet_out(&enpub->enp_mm, packet_out);
|
||||
|
|
|
@ -90,6 +90,10 @@ typedef struct lsquic_packet_out
|
|||
#define POLEV_SHIFT 18
|
||||
PO_BITS_2 = (1 <<18), /* PO_BITS_2 and PO_BITS_3 encode the */
|
||||
PO_BITS_3 = (1 <<19), /* crypto level. Used for logging. */
|
||||
#define POIPv6_SHIFT 20
|
||||
PO_IPv6 = (1 <<20), /* Set if pmi_allocate was passed is_ipv6=1,
|
||||
* otherwise unset.
|
||||
*/
|
||||
} po_flags;
|
||||
enum quic_ft_bit po_frame_types:16; /* Bitmask of QUIC_FRAME_* */
|
||||
unsigned short po_data_sz; /* Number of usable bytes in data */
|
||||
|
@ -142,6 +146,13 @@ typedef struct lsquic_packet_out
|
|||
(p)->po_flags |= ((b) & 0x3) << POBIT_SHIFT; \
|
||||
} while (0)
|
||||
|
||||
#define lsquic_packet_out_ipv6(p) ((int)(((p)->po_flags >> POIPv6_SHIFT) & 1))
|
||||
|
||||
#define lsquic_packet_out_set_ipv6(p, b) do { \
|
||||
(p)->po_flags &= ~(1 << POIPv6_SHIFT); \
|
||||
(p)->po_flags |= ((b) & 1) << POIPv6_SHIFT; \
|
||||
} while (0)
|
||||
|
||||
#define lsquic_po_header_length(lconn, po_flags) ( \
|
||||
lconn->cn_pf->pf_packout_header_size(lconn, po_flags))
|
||||
|
||||
|
@ -198,7 +209,7 @@ lsquic_packet_out_new (struct lsquic_mm *, struct malo *, int use_cid,
|
|||
|
||||
void
|
||||
lsquic_packet_out_destroy (lsquic_packet_out_t *,
|
||||
struct lsquic_engine_public *);
|
||||
struct lsquic_engine_public *, void *peer_ctx);
|
||||
|
||||
int
|
||||
lsquic_packet_out_add_stream (lsquic_packet_out_t *packet_out,
|
||||
|
|
|
@ -528,12 +528,22 @@ send_ctl_release_enc_data (struct lsquic_send_ctl *ctl,
|
|||
struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
ctl->sc_enpub->enp_pmi->pmi_release(ctl->sc_enpub->enp_pmi_ctx,
|
||||
packet_out->po_enc_data);
|
||||
ctl->sc_conn_pub->lconn->cn_peer_ctx, packet_out->po_enc_data,
|
||||
lsquic_packet_out_ipv6(packet_out));
|
||||
packet_out->po_flags &= ~PO_ENCRYPTED;
|
||||
packet_out->po_enc_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
send_ctl_destroy_packet (struct lsquic_send_ctl *ctl,
|
||||
struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub,
|
||||
ctl->sc_conn_pub->lconn->cn_peer_ctx);
|
||||
}
|
||||
|
||||
|
||||
/* Returns true if packet was rescheduled, false otherwise. In the latter
|
||||
* case, you should not dereference packet_out after the function returns.
|
||||
*/
|
||||
|
@ -564,7 +574,7 @@ send_ctl_handle_lost_packet (lsquic_send_ctl_t *ctl,
|
|||
{
|
||||
LSQ_DEBUG("lost unretransmittable packet %"PRIu64,
|
||||
packet_out->po_packno);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -754,7 +764,7 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl,
|
|||
lsquic_cubic_ack(&ctl->sc_cubic, now, now - packet_out->po_sent,
|
||||
app_limited, packet_sz);
|
||||
lsquic_packet_out_ack_streams(packet_out);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
}
|
||||
packet_out = next;
|
||||
}
|
||||
|
@ -853,7 +863,7 @@ lsquic_send_ctl_cleanup (lsquic_send_ctl_t *ctl)
|
|||
while ((packet_out = TAILQ_FIRST(&ctl->sc_scheduled_packets)))
|
||||
{
|
||||
send_ctl_sched_remove(ctl, packet_out);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
}
|
||||
assert(0 == ctl->sc_n_scheduled);
|
||||
assert(0 == ctl->sc_bytes_scheduled);
|
||||
|
@ -861,7 +871,7 @@ lsquic_send_ctl_cleanup (lsquic_send_ctl_t *ctl)
|
|||
{
|
||||
TAILQ_REMOVE(&ctl->sc_unacked_packets, packet_out, po_next);
|
||||
ctl->sc_bytes_unacked_all -= packet_out_total_sz(packet_out);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
--ctl->sc_n_in_flight_all;
|
||||
}
|
||||
assert(0 == ctl->sc_n_in_flight_all);
|
||||
|
@ -869,7 +879,7 @@ lsquic_send_ctl_cleanup (lsquic_send_ctl_t *ctl)
|
|||
while ((packet_out = TAILQ_FIRST(&ctl->sc_lost_packets)))
|
||||
{
|
||||
TAILQ_REMOVE(&ctl->sc_lost_packets, packet_out, po_next);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
}
|
||||
pacer_cleanup(&ctl->sc_pacer);
|
||||
#if LSQUIC_SEND_STATS
|
||||
|
@ -1100,7 +1110,7 @@ lsquic_send_ctl_next_packet_to_send (lsquic_send_ctl_t *ctl)
|
|||
{
|
||||
LSQ_DEBUG("Dropping packet %"PRIu64" from scheduled queue",
|
||||
packet_out->po_packno);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
goto get_packet;
|
||||
}
|
||||
}
|
||||
|
@ -1166,7 +1176,7 @@ send_ctl_allocate_packet (lsquic_send_ctl_t *ctl, enum lsquic_packno_bits bits,
|
|||
LSQ_ERROR("wanted to allocate packet with at least %u bytes of "
|
||||
"payload, but only got %u bytes (mtu: %u bytes)", need_at_least,
|
||||
lsquic_packet_out_avail(packet_out), ctl->sc_pack_size);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1311,7 +1321,7 @@ lsquic_send_ctl_reschedule_packets (lsquic_send_ctl_t *ctl)
|
|||
{
|
||||
LSQ_DEBUG("Dropping packet %"PRIu64" from unacked queue",
|
||||
packet_out->po_packno);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1373,7 +1383,7 @@ lsquic_send_ctl_elide_stream_frames (lsquic_send_ctl_t *ctl, uint32_t stream_id)
|
|||
LSQ_DEBUG("cancel packet %"PRIu64" after eliding frames for "
|
||||
"stream %"PRIu32, packet_out->po_packno, stream_id);
|
||||
send_ctl_sched_remove(ctl, packet_out);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
++dropped;
|
||||
}
|
||||
}
|
||||
|
@ -1398,7 +1408,7 @@ lsquic_send_ctl_elide_stream_frames (lsquic_send_ctl_t *ctl, uint32_t stream_id)
|
|||
TAILQ_REMOVE(&ctl->sc_buffered_packets[n].bpq_packets,
|
||||
packet_out, po_next);
|
||||
--ctl->sc_buffered_packets[n].bpq_count;
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
LSQ_DEBUG("Elide packet from buffered queue #%u; count: %u",
|
||||
n, ctl->sc_buffered_packets[n].bpq_count);
|
||||
}
|
||||
|
@ -1508,7 +1518,7 @@ lsquic_send_ctl_squeeze_sched (lsquic_send_ctl_t *ctl)
|
|||
send_ctl_sched_remove(ctl, packet_out);
|
||||
LSQ_DEBUG("Dropping packet %"PRIu64" from scheduled queue",
|
||||
packet_out->po_packno);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
++dropped;
|
||||
}
|
||||
}
|
||||
|
@ -1560,7 +1570,7 @@ lsquic_send_ctl_drop_scheduled (lsquic_send_ctl_t *ctl)
|
|||
while ((packet_out = TAILQ_FIRST(&ctl->sc_scheduled_packets)))
|
||||
{
|
||||
send_ctl_sched_remove(ctl, packet_out);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
}
|
||||
assert(0 == ctl->sc_n_scheduled);
|
||||
ctl->sc_cur_packno = lsquic_senhist_largest(&ctl->sc_senhist);
|
||||
|
@ -1743,7 +1753,7 @@ split_buffered_packet (lsquic_send_ctl_t *ctl,
|
|||
}
|
||||
else
|
||||
{
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue