mirror of
https://github.com/obgm/libcoap.git
synced 2026-11-12 11:40:39 +03:00
Merge pull request #512 from mrdeep1/tcp_fixes
TCP: Prevent incorrectly formed PDUs causing RAM exhaustion.
This commit is contained in:
4 files changed
+36
-5
No files matched your search
@@ -63,7 +63,7 @@ typedef struct coap_session_t {
|
||||
coap_session_state_t state; /**< current state of relationaship with peer */
|
||||
unsigned ref; /**< reference count from queues */
|
||||
unsigned tls_overhead; /**< overhead of TLS layer */
|
||||
unsigned mtu; /**< path or CSM mtu */
|
||||
uint64_t mtu; /**< path or CSM mtu */
|
||||
coap_address_t local_if; /**< optional local interface address */
|
||||
UT_hash_handle hh;
|
||||
coap_addr_tuple_t addr_info; /**< key: remote/local address info */
|
||||
@@ -74,6 +74,7 @@ typedef struct coap_session_t {
|
||||
void *tls; /**< security parameters */
|
||||
uint16_t tx_mid; /**< the last message id that was used in this session */
|
||||
uint8_t con_active; /**< Active CON request sent */
|
||||
uint8_t csm_block_supported; /**< CSM TCP blocks supported */
|
||||
coap_tid_t last_ping_mid; /**< the last keepalive message id that was used in this session */
|
||||
struct coap_queue_t *delayqueue; /**< list of delayed messages waiting to be sent */
|
||||
size_t partial_write; /**< if > 0 indicates number of bytes already written from the pdu at the head of sendqueue */
|
||||
|
||||
+2
-2
@@ -45,10 +45,10 @@ struct coap_session_t;
|
||||
|
||||
#ifndef COAP_DEFAULT_MAX_PDU_RX_SIZE
|
||||
#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
|
||||
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (COAP_MAX_MESSAGE_SIZE_TCP16+4)
|
||||
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (COAP_MAX_MESSAGE_SIZE_TCP16+4UL)
|
||||
#else
|
||||
/* 8 MiB max-message-size plus some space for options */
|
||||
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (8*1024*1024+256)
|
||||
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (8UL*1024*1024+256)
|
||||
#endif
|
||||
#endif /* COAP_DEFAULT_MAX_PDU_RX_SIZE */
|
||||
|
||||
|
||||
+4
-1
@@ -314,11 +314,14 @@ void coap_session_send_csm(coap_session_t *session) {
|
||||
session->partial_write = 0;
|
||||
if (session->mtu == 0)
|
||||
session->mtu = COAP_DEFAULT_MTU; /* base value */
|
||||
pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_SIGNALING_CSM, 0, 16);
|
||||
pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_SIGNALING_CSM, 0, 20);
|
||||
if ( pdu == NULL
|
||||
|| coap_add_option(pdu, COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE,
|
||||
coap_encode_var_safe(buf, sizeof(buf),
|
||||
COAP_DEFAULT_MAX_PDU_RX_SIZE), buf) == 0
|
||||
|| coap_add_option(pdu, COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER,
|
||||
coap_encode_var_safe(buf, sizeof(buf),
|
||||
0), buf) == 0
|
||||
|| coap_pdu_encode_header(pdu, session->proto) == 0
|
||||
) {
|
||||
coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE);
|
||||
|
||||
@@ -1003,6 +1003,25 @@ coap_send(coap_session_t *session, coap_pdu_t *pdu) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if !COAP_DISABLE_TCP
|
||||
if (COAP_PROTO_RELIABLE(session->proto) && !session->csm_block_supported) {
|
||||
/*
|
||||
* Need to check that this instance is not sending any block options as the
|
||||
* remote end via CSM has not informed us that there is support
|
||||
* https://tools.ietf.org/html/rfc8323#section-5.3.2
|
||||
* Note that this also includes BERT which is application specific.
|
||||
*/
|
||||
coap_opt_iterator_t opt_iter;
|
||||
|
||||
if (coap_check_option(pdu, COAP_OPTION_BLOCK1, &opt_iter) != NULL) {
|
||||
goto error;
|
||||
}
|
||||
if (coap_check_option(pdu, COAP_OPTION_BLOCK2, &opt_iter) != NULL) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
#endif /* !COAP_DISABLE_TCP */
|
||||
|
||||
bytes_written = coap_send_pdu( session, pdu, NULL );
|
||||
|
||||
if (bytes_written == COAP_PDU_DELAYED) {
|
||||
@@ -1337,6 +1356,14 @@ coap_read_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now)
|
||||
if (n == len) {
|
||||
size_t size = coap_pdu_parse_size(session->proto, session->read_header,
|
||||
hdr_size);
|
||||
if (size > COAP_DEFAULT_MAX_PDU_RX_SIZE) {
|
||||
coap_log(LOG_WARNING,
|
||||
"** %s: incoming PDU length too large (%zu > %lu)\n",
|
||||
coap_session_str(session),
|
||||
size, COAP_DEFAULT_MAX_PDU_RX_SIZE);
|
||||
bytes_read = -1;
|
||||
break;
|
||||
}
|
||||
session->partial_pdu = coap_pdu_init(0, 0, 0, size);
|
||||
if (session->partial_pdu == NULL) {
|
||||
bytes_read = -1;
|
||||
@@ -2395,7 +2422,7 @@ handle_signaling(coap_context_t *context, coap_session_t *session,
|
||||
coap_session_set_mtu(session, coap_decode_var_bytes(coap_opt_value(option),
|
||||
coap_opt_length(option)));
|
||||
} else if (opt_iter.type == COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER) {
|
||||
/* ... */
|
||||
session->csm_block_supported = 1;
|
||||
}
|
||||
}
|
||||
if (session->state == COAP_SESSION_STATE_CSM)
|
||||
|
||||
Reference in new issue
Block a user