Bug 32040: Add a keep_*_mask to keep circpad machines

Allows us to program machines that stay around after creation if circuit state
or purpose changes.
This commit is contained in:
Mike Perry 2020-06-09 02:36:45 -05:00
parent 285dbeefa1
commit f697ac5861
3 changed files with 50 additions and 15 deletions

View File

@ -2008,7 +2008,7 @@ circpad_internal_event_state_length_up(circpad_machine_runtime_t *mi)
* Returns true if the circuit matches the conditions.
*/
static inline bool
circpad_machine_conditions_met(origin_circuit_t *circ,
circpad_machine_conditions_apply(origin_circuit_t *circ,
const circpad_machine_spec_t *machine)
{
/* If padding is disabled, no machines should match/apply. This has
@ -2025,7 +2025,7 @@ circpad_machine_conditions_met(origin_circuit_t *circ,
}
if (!(circpad_circ_purpose_to_mask(TO_CIRCUIT(circ)->purpose)
& machine->conditions.purpose_mask))
& machine->conditions.apply_purpose_mask))
return 0;
if (machine->conditions.requires_vanguards) {
@ -2041,7 +2041,7 @@ circpad_machine_conditions_met(origin_circuit_t *circ,
* "I want to apply to circuits with either streams or no streams"; OR
* "I only want to apply to circuits with streams"; OR
* "I only want to apply to circuits without streams". */
if (!(circpad_circuit_state(circ) & machine->conditions.state_mask))
if (!(circpad_circuit_state(circ) & machine->conditions.apply_state_mask))
return 0;
if (circuit_get_cpath_opened_len(circ) < machine->conditions.min_hops)
@ -2050,6 +2050,26 @@ circpad_machine_conditions_met(origin_circuit_t *circ,
return 1;
}
/**
* Check to see if any of the keep conditions still apply to this circuit.
*
* These conditions keep the machines active if they match, but do not
* cause new machines to start up.
*/
static inline bool
circpad_machine_conditions_keep(origin_circuit_t *circ,
const circpad_machine_spec_t *machine)
{
if ((circpad_circ_purpose_to_mask(TO_CIRCUIT(circ)->purpose)
& machine->conditions.keep_purpose_mask))
return 1;
if ((circpad_circuit_state(circ) & machine->conditions.keep_state_mask))
return 1;
return 0;
}
/**
* Returns a minimized representation of the circuit state.
*
@ -2115,7 +2135,12 @@ circpad_shutdown_old_machines(origin_circuit_t *on_circ)
circuit_t *circ = TO_CIRCUIT(on_circ);
FOR_EACH_ACTIVE_CIRCUIT_MACHINE_BEGIN(i, circ) {
if (!circpad_machine_conditions_met(on_circ,
/* We shut down a machine if neither the apply conditions
* nor the keep conditions match. If either set of conditions match,
* keep it around. */
if (!circpad_machine_conditions_apply(on_circ,
circ->padding_machine[i]) &&
!circpad_machine_conditions_keep(on_circ,
circ->padding_machine[i])) {
uint32_t machine_ctr = circ->padding_info[i]->machine_ctr;
// Clear machineinfo (frees timers)
@ -2174,7 +2199,7 @@ circpad_add_matching_machines(origin_circuit_t *on_circ,
* machines installed on a circuit. Make sure we only
* add this machine if its target machine index is free. */
if (machine->machine_index == i &&
circpad_machine_conditions_met(on_circ, machine)) {
circpad_machine_conditions_apply(on_circ, machine)) {
// We can only replace this machine if the target hopnum
// is the same, otherwise we'll get invalid data
@ -2587,9 +2612,9 @@ circpad_circ_client_machine_init(void)
= tor_malloc_zero(sizeof(circpad_machine_spec_t));
circ_client_machine->conditions.min_hops = 2;
circ_client_machine->conditions.state_mask =
circ_client_machine->conditions.apply_state_mask =
CIRCPAD_CIRC_BUILDING|CIRCPAD_CIRC_OPENED|CIRCPAD_CIRC_HAS_RELAY_EARLY;
circ_client_machine->conditions.purpose_mask = CIRCPAD_PURPOSE_ALL;
circ_client_machine->conditions.apply_purpose_mask = CIRCPAD_PURPOSE_ALL;
circ_client_machine->conditions.reduced_padding_ok = 1;
circ_client_machine->target_hopnum = 2;

View File

@ -173,11 +173,21 @@ typedef struct circpad_machine_conditions_t {
/** Only apply the machine *if* the circuit's state matches any of
* the bits set in this bitmask. */
circpad_circuit_state_t state_mask;
circpad_circuit_state_t apply_state_mask;
/** Only apply a machine *if* the circuit's purpose matches one
* of the bits set in this bitmask */
circpad_purpose_mask_t purpose_mask;
circpad_purpose_mask_t apply_purpose_mask;
/** Keep a machine if any of the circuits's state machine's match
* the bits set in this bitmask, but don't apply new machines if
* they match this mask. */
circpad_circuit_state_t keep_state_mask;
/** Keep a machine if any of the circuits's state machine's match
* the bits set in this bitmask, but don't apply new machines if
* they match this mask. */
circpad_purpose_mask_t keep_purpose_mask;
} circpad_machine_conditions_t;

View File

@ -67,7 +67,7 @@ circpad_machine_client_hide_intro_circuits(smartlist_t *machines_sl)
client_machine->name = "client_ip_circ";
client_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
client_machine->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED;
client_machine->target_hopnum = 2;
/* This is a client machine */
@ -102,7 +102,7 @@ circpad_machine_client_hide_intro_circuits(smartlist_t *machines_sl)
* INTRO_MACHINE_MAXIMUM_PADDING cells, to match the "...(inbound data cells
* continue)" portion of the trace (aka the rest of an HTTPS response body).
*/
client_machine->conditions.purpose_mask =
client_machine->conditions.apply_purpose_mask =
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)|
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_INTRODUCE_ACKED)|
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_CIRCUIT_PADDING);
@ -152,7 +152,7 @@ circpad_machine_relay_hide_intro_circuits(smartlist_t *machines_sl)
relay_machine->name = "relay_ip_circ";
relay_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
relay_machine->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED;
/* This is a relay-side machine */
relay_machine->is_origin_side = 0;
@ -263,7 +263,7 @@ circpad_machine_client_hide_rend_circuits(smartlist_t *machines_sl)
client_machine->name = "client_rp_circ";
/* Only pad after the circuit has been built and pad to the middle */
client_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
client_machine->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED;
client_machine->target_hopnum = 2;
/* This is a client machine */
@ -299,7 +299,7 @@ circpad_machine_client_hide_rend_circuits(smartlist_t *machines_sl)
*
* Hence this way we make rendezvous circuits look like general circuits up
* till the end of the circuit setup. */
client_machine->conditions.purpose_mask =
client_machine->conditions.apply_purpose_mask =
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_REND_JOINED)|
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_REND_READY)|
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED);
@ -383,7 +383,7 @@ circpad_machine_relay_hide_rend_circuits(smartlist_t *machines_sl)
/* Only pad after the circuit has been built and pad to the middle */
relay_machine->conditions.min_hops = 2;
relay_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
relay_machine->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED;
/* This is a relay-side machine */
relay_machine->is_origin_side = 0;