Fix run_orphan DOS (#10290)

Co-authored-by: Carl <carl@solana.com>
This commit is contained in:
carllin
2020-05-28 11:29:13 -07:00
committed by GitHub
parent 93506b22e7
commit bc86ee8d13

View File

@ -590,6 +590,8 @@ impl ServeRepair {
); );
if let Some(packet) = packet { if let Some(packet) = packet {
res.packets.push(packet); res.packets.push(packet);
} else {
break;
} }
if meta.is_parent_set() && res.packets.len() <= max_responses { if meta.is_parent_set() && res.packets.len() <= max_responses {
slot = meta.parent_slot; slot = meta.parent_slot;
@ -864,6 +866,8 @@ mod tests {
// Should not panic. // Should not panic.
run_orphan(UNLOCK_NONCE_SLOT, 3, None); run_orphan(UNLOCK_NONCE_SLOT, 3, None);
run_orphan(UNLOCK_NONCE_SLOT, 3, Some(9)); run_orphan(UNLOCK_NONCE_SLOT, 3, Some(9));
// Giving no nonce after UNLOCK_NONCE_SLOT should return empty
run_orphan(UNLOCK_NONCE_SLOT + 1, 3, None);
} }
fn run_orphan(slot: Slot, num_slots: u64, nonce: Option<Nonce>) { fn run_orphan(slot: Slot, num_slots: u64, nonce: Option<Nonce>) {
@ -902,40 +906,47 @@ mod tests {
// For a orphan request for `slot + num_slots - 1`, we should return the highest shreds // For a orphan request for `slot + num_slots - 1`, we should return the highest shreds
// from slots in the range [slot, slot + num_slots - 1] // from slots in the range [slot, slot + num_slots - 1]
let rv: Vec<_> = ServeRepair::run_orphan( let rv = ServeRepair::run_orphan(
&recycler, &recycler,
&socketaddr_any!(), &socketaddr_any!(),
Some(&blockstore), Some(&blockstore),
slot + num_slots - 1, slot + num_slots - 1,
5, 5,
nonce, nonce,
) );
.expect("run_orphan packets")
.packets
.iter()
.map(|b| b.clone())
.collect();
// Verify responses if Shred::is_nonce_unlocked(slot + num_slots - 1) && nonce.is_none() {
let expected: Vec<_> = (slot..slot + num_slots) // If a nonce is expected but not provided, there should be no
.rev() // response
.filter_map(|slot| { assert!(rv.is_none());
let nonce = if Shred::is_nonce_unlocked(slot) { } else {
nonce // Verify responses
} else { let rv: Vec<_> = rv
None .expect("run_orphan packets")
}; .packets
let index = blockstore.meta(slot).unwrap().unwrap().received - 1; .iter()
repair_response::repair_response_packet( .map(|b| b.clone())
&blockstore, .collect();
slot, let expected: Vec<_> = (slot..slot + num_slots)
index, .rev()
&socketaddr_any!(), .filter_map(|slot| {
nonce, let nonce = if Shred::is_nonce_unlocked(slot) {
) nonce
}) } else {
.collect(); None
assert_eq!(rv, expected); };
let index = blockstore.meta(slot).unwrap().unwrap().received - 1;
repair_response::repair_response_packet(
&blockstore,
slot,
index,
&socketaddr_any!(),
nonce,
)
})
.collect();
assert_eq!(rv, expected);
}
} }
Blockstore::destroy(&ledger_path).expect("Expected successful database destruction"); Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");