mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-13 22:53:44 +01:00
conflux: Avoid noting a cell was sent on a closed circuit
It turns out that circuit_package_relay_cell() returns 0 in order to drop a cell but there is a code path, if the circuit queue is full, that also silently closes the circuit and returns 0. This lead to Conflux thinking a cell was sent but actually the cell was not and the circuit was closed leading to the hard assert. And so this function makes sure that circuit_package_relay_cell() and append_cell_to_circuit_queue() returns a value that indicate what happened with the cell and circuit so the caller can make an informed decision with it. This change makes it that we do NOT enter the Conflux subsystem if the cell is not queued on the circuit. Fixes #40921 Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
6ebf436084
commit
269b4561a1
3
changes/ticket40921
Normal file
3
changes/ticket40921
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
o Minor bugfixes (conflux):
|
||||||
|
- Avoid a potential hard assert (crash) when sending a cell on a Conflux
|
||||||
|
set. Fixes bug 40921; bugfix on 0.4.8.1-alpha.
|
@ -816,8 +816,10 @@ circuit_deliver_create_cell,(circuit_t *circ,
|
|||||||
circuit_set_n_circid_chan(circ, id, circ->n_chan);
|
circuit_set_n_circid_chan(circ, id, circ->n_chan);
|
||||||
cell.circ_id = circ->n_circ_id;
|
cell.circ_id = circ->n_circ_id;
|
||||||
|
|
||||||
append_cell_to_circuit_queue(circ, circ->n_chan, &cell,
|
if (append_cell_to_circuit_queue(circ, circ->n_chan, &cell,
|
||||||
CELL_DIRECTION_OUT, 0);
|
CELL_DIRECTION_OUT, 0) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
/* Update began timestamp for circuits starting their first hop */
|
/* Update began timestamp for circuits starting their first hop */
|
||||||
|
@ -531,7 +531,10 @@ conflux_note_cell_sent(conflux_t *cfx, circuit_t *circ, uint8_t relay_command)
|
|||||||
}
|
}
|
||||||
|
|
||||||
leg = conflux_get_leg(cfx, circ);
|
leg = conflux_get_leg(cfx, circ);
|
||||||
tor_assert(leg);
|
if (leg == NULL) {
|
||||||
|
log_fn(LOG_PROTOCOL_WARN, LD_BUG, "No Conflux leg after sending a cell");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
leg->last_seq_sent++;
|
leg->last_seq_sent++;
|
||||||
|
|
||||||
|
@ -365,14 +365,19 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
|
|||||||
* we might kill the circ before we relay
|
* we might kill the circ before we relay
|
||||||
* the cells. */
|
* the cells. */
|
||||||
|
|
||||||
append_cell_to_circuit_queue(circ, chan, cell, cell_direction, 0);
|
if (append_cell_to_circuit_queue(circ, chan, cell, cell_direction, 0) < 0) {
|
||||||
|
return -END_CIRC_REASON_RESOURCELIMIT;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Package a relay cell from an edge:
|
/** Package a relay cell from an edge:
|
||||||
* - Encrypt it to the right layer
|
* - Encrypt it to the right layer
|
||||||
* - Append it to the appropriate cell_queue on <b>circ</b>.
|
* - Append it to the appropriate cell_queue on <b>circ</b>.
|
||||||
*/
|
*
|
||||||
|
* Return 1 if the cell was successfully sent as in queued on the circuit.
|
||||||
|
* Return 0 if the cell needs to be dropped as in ignored.
|
||||||
|
* Return -1 on error for which the circuit should be marked for close. */
|
||||||
MOCK_IMPL(int,
|
MOCK_IMPL(int,
|
||||||
circuit_package_relay_cell, (cell_t *cell, circuit_t *circ,
|
circuit_package_relay_cell, (cell_t *cell, circuit_t *circ,
|
||||||
cell_direction_t cell_direction,
|
cell_direction_t cell_direction,
|
||||||
@ -430,8 +435,8 @@ circuit_package_relay_cell, (cell_t *cell, circuit_t *circ,
|
|||||||
}
|
}
|
||||||
++stats_n_relay_cells_relayed;
|
++stats_n_relay_cells_relayed;
|
||||||
|
|
||||||
append_cell_to_circuit_queue(circ, chan, cell, cell_direction, on_stream);
|
return append_cell_to_circuit_queue(circ, chan, cell,
|
||||||
return 0;
|
cell_direction, on_stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If cell's stream_id matches the stream_id of any conn that's
|
/** If cell's stream_id matches the stream_id of any conn that's
|
||||||
@ -742,13 +747,24 @@ relay_send_command_from_edge_,(streamid_t stream_id, circuit_t *orig_circ,
|
|||||||
circuit_sent_valid_data(origin_circ, rh.length);
|
circuit_sent_valid_data(origin_circ, rh.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer,
|
int ret = circuit_package_relay_cell(&cell, circ, cell_direction,
|
||||||
stream_id, filename, lineno) < 0) {
|
cpath_layer, stream_id, filename,
|
||||||
|
lineno);
|
||||||
|
if (ret < 0) {
|
||||||
log_warn(LD_BUG,"circuit_package_relay_cell failed. Closing.");
|
log_warn(LD_BUG,"circuit_package_relay_cell failed. Closing.");
|
||||||
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
||||||
return -1;
|
return -1;
|
||||||
|
} else if (ret == 0) {
|
||||||
|
/* This means we should drop the cell or that the circuit was already
|
||||||
|
* marked for close. At this point in time, we do NOT close the circuit if
|
||||||
|
* the cell is dropped. It is not the case with arti where each circuit
|
||||||
|
* protocol violation will lead to closing the circuit. */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* At this point, we are certain that the cell was queued on the circuit and
|
||||||
|
* thus will be sent on the wire. */
|
||||||
|
|
||||||
if (circ->conflux) {
|
if (circ->conflux) {
|
||||||
conflux_note_cell_sent(circ->conflux, circ, relay_command);
|
conflux_note_cell_sent(circ->conflux, circ, relay_command);
|
||||||
}
|
}
|
||||||
@ -3381,8 +3397,13 @@ relay_consensus_has_changed(const networkstatus_t *ns)
|
|||||||
* The given <b>cell</b> is copied onto the circuit queue so the caller must
|
* The given <b>cell</b> is copied onto the circuit queue so the caller must
|
||||||
* cleanup the memory.
|
* cleanup the memory.
|
||||||
*
|
*
|
||||||
* This function is part of the fast path. */
|
* This function is part of the fast path.
|
||||||
void
|
*
|
||||||
|
* Return 1 if the cell was successfully sent.
|
||||||
|
* Return 0 if the cell can not be sent. The caller MUST NOT close the circuit.
|
||||||
|
* Return -1 indicating an error and that the caller should mark the circuit
|
||||||
|
* for close. */
|
||||||
|
int
|
||||||
append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
||||||
cell_t *cell, cell_direction_t direction,
|
cell_t *cell, cell_direction_t direction,
|
||||||
streamid_t fromstream)
|
streamid_t fromstream)
|
||||||
@ -3393,8 +3414,9 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
|||||||
int32_t max_queue_size;
|
int32_t max_queue_size;
|
||||||
int circ_blocked;
|
int circ_blocked;
|
||||||
int exitward;
|
int exitward;
|
||||||
if (circ->marked_for_close)
|
if (circ->marked_for_close) {
|
||||||
return;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
exitward = (direction == CELL_DIRECTION_OUT);
|
exitward = (direction == CELL_DIRECTION_OUT);
|
||||||
if (exitward) {
|
if (exitward) {
|
||||||
@ -3424,9 +3446,8 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
|||||||
"Closing circuit for safety reasons.",
|
"Closing circuit for safety reasons.",
|
||||||
(exitward) ? "Outbound" : "Inbound", queue->n,
|
(exitward) ? "Outbound" : "Inbound", queue->n,
|
||||||
max_queue_size);
|
max_queue_size);
|
||||||
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
|
|
||||||
stats_n_circ_max_cell_reached++;
|
stats_n_circ_max_cell_reached++;
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Very important that we copy to the circuit queue because all calls to
|
/* Very important that we copy to the circuit queue because all calls to
|
||||||
@ -3437,8 +3458,9 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
|||||||
/* Check and run the OOM if needed. */
|
/* Check and run the OOM if needed. */
|
||||||
if (PREDICT_UNLIKELY(cell_queues_check_size())) {
|
if (PREDICT_UNLIKELY(cell_queues_check_size())) {
|
||||||
/* We ran the OOM handler which might have closed this circuit. */
|
/* We ran the OOM handler which might have closed this circuit. */
|
||||||
if (circ->marked_for_close)
|
if (circ->marked_for_close) {
|
||||||
return;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have too many cells on the circuit, note that it should
|
/* If we have too many cells on the circuit, note that it should
|
||||||
@ -3462,6 +3484,7 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
|||||||
|
|
||||||
/* New way: mark this as having waiting cells for the scheduler */
|
/* New way: mark this as having waiting cells for the scheduler */
|
||||||
scheduler_channel_has_waiting_cells(chan);
|
scheduler_channel_has_waiting_cells(chan);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Append an encoded value of <b>addr</b> to <b>payload_out</b>, which must
|
/** Append an encoded value of <b>addr</b> to <b>payload_out</b>, which must
|
||||||
|
@ -76,7 +76,7 @@ void cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
|
|||||||
int exitward, const cell_t *cell,
|
int exitward, const cell_t *cell,
|
||||||
int wide_circ_ids, int use_stats);
|
int wide_circ_ids, int use_stats);
|
||||||
|
|
||||||
void append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
int append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
||||||
cell_t *cell, cell_direction_t direction,
|
cell_t *cell, cell_direction_t direction,
|
||||||
streamid_t fromstream);
|
streamid_t fromstream);
|
||||||
|
|
||||||
|
@ -579,8 +579,10 @@ onionskin_answer(struct or_circuit_t *circ,
|
|||||||
|
|
||||||
int used_create_fast = (created_cell->cell_type == CELL_CREATED_FAST);
|
int used_create_fast = (created_cell->cell_type == CELL_CREATED_FAST);
|
||||||
|
|
||||||
append_cell_to_circuit_queue(TO_CIRCUIT(circ),
|
if (append_cell_to_circuit_queue(TO_CIRCUIT(circ), circ->p_chan,
|
||||||
circ->p_chan, &cell, CELL_DIRECTION_IN, 0);
|
&cell, CELL_DIRECTION_IN, 0) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
log_debug(LD_CIRC,"Finished sending '%s' cell.",
|
log_debug(LD_CIRC,"Finished sending '%s' cell.",
|
||||||
used_create_fast ? "created_fast" : "created");
|
used_create_fast ? "created_fast" : "created");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user