Commit adb248b6 authored by David Goulet's avatar David Goulet 🔆 Committed by Nick Mathewson
Browse files

TROVE-2021-003: Check layer_hint before half-closed end and resolve cells

This issue was reported by Jann Horn part of Google's Project Zero.

Jann's one-sentence summary: entry/middle relays can spoof RELAY_END cells on
half-closed streams, which can lead to stream confusion between OP and

Fixes #40389
parent d71bf986
o Major bugfixes (relay, TROVE):
- Don't allow entry or middle relays to spoof RELAY_END or RELAY_RESOLVED
cell on half-closed streams. Fixes bug 40389; bugfix on
......@@ -1428,6 +1428,25 @@ connection_edge_process_relay_cell_not_open(
// return -1;
* Return true iff our decryption layer_hint is from the last hop
* in a circuit.
static bool
relay_crypt_from_last_hop(origin_circuit_t *circ, crypt_path_t *layer_hint)
if (layer_hint != circ->cpath->prev) {
"Got unexpected relay data from intermediate hop");
return false;
return true;
/** An incoming relay cell has arrived on circuit <b>circ</b>. If
* <b>conn</b> is NULL this is a control cell, else <b>cell</b> is
* destined for <b>conn</b>.
......@@ -1616,7 +1635,8 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (!conn) {
if (CIRCUIT_IS_ORIGIN(circ)) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
if (connection_half_edge_is_valid_end(ocirc->half_streams,
if (relay_crypt_from_last_hop(ocirc, layer_hint) &&
rh.stream_id)) {
circuit_read_valid_data(ocirc, rh.length);
......@@ -1918,7 +1938,8 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (CIRCUIT_IS_ORIGIN(circ)) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
if (connection_half_edge_is_valid_resolved(ocirc->half_streams,
if (relay_crypt_from_last_hop(ocirc, layer_hint) &&
rh.stream_id)) {
circuit_read_valid_data(ocirc, rh.length);
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment