Merge pull request #512 from mrdeep1/tcp_fixes

TCP: Prevent incorrectly formed PDUs causing RAM exhaustion.
This commit is contained in:
obgm authored and GitHub committed 2020-06-30 14:04:20 +02:00
commit 098fa85395
4 files changed
+36 -5

No files matched your search

+2 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+28 -1
View File
@@ -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)