diff options
-rw-r--r-- | changes/bug10363 | 6 | ||||
-rw-r--r-- | src/or/channeltls.c | 23 |
2 files changed, 21 insertions, 8 deletions
diff --git a/changes/bug10363 b/changes/bug10363 new file mode 100644 index 0000000000..cf5b7fdc89 --- /dev/null +++ b/changes/bug10363 @@ -0,0 +1,6 @@ + o Major bugfixes: + - Fix two instances of possible undefined behavior in channeltls.c + that could, under unlucky circumstances, have led to a pointer + overflow. Fixes bug #10363; bugfixes on 0.2.0.10-alpha and + 0.2.3.6-alpha. Reported by "bobnomnom". + diff --git a/src/or/channeltls.c b/src/or/channeltls.c index f751c0da99..d59083b338 100644 --- a/src/or/channeltls.c +++ b/src/or/channeltls.c @@ -1174,7 +1174,6 @@ static void channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan) { int highest_supported_version = 0; - const uint8_t *cp, *end; int started_here = 0; tor_assert(cell); @@ -1206,11 +1205,15 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan) } tor_assert(chan->conn->handshake_state); - end = cell->payload + cell->payload_len; - for (cp = cell->payload; cp+1 < end; cp += 2) { - uint16_t v = ntohs(get_uint16(cp)); - if (is_or_protocol_version_known(v) && v > highest_supported_version) - highest_supported_version = v; + + { + int i; + const uint8_t *cp = cell->payload; + for (i = 0; i < cell->payload_len / 2; ++i, cp += 2) { + uint16_t v = ntohs(get_uint16(cp)); + if (is_or_protocol_version_known(v) && v > highest_supported_version) + highest_supported_version = v; + } } if (!highest_supported_version) { log_fn(LOG_PROTOCOL_WARN, LD_OR, @@ -1567,12 +1570,16 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan) for (i = 0; i < n_certs; ++i) { uint8_t cert_type; uint16_t cert_len; - if (ptr + 3 > cell->payload + cell->payload_len) { + if (cell->payload_len < 3) + goto truncated; + if (ptr > cell->payload + cell->payload_len - 3) { goto truncated; } cert_type = *ptr; cert_len = ntohs(get_uint16(ptr+1)); - if (ptr + 3 + cert_len > cell->payload + cell->payload_len) { + if (cell->payload_len < 3 + cert_len) + goto truncated; + if (ptr > cell->payload + cell->payload_len - cert_len - 3) { goto truncated; } if (cert_type == OR_CERT_TYPE_TLS_LINK || |