Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 5dbf7d8

Browse files
authored
removes raw indexing into packet data (#25554)
Packets are at the boundary of the system where, vast majority of the time, they are received from an untrusted source. Raw indexing into the data buffer can open attack vectors if the offsets are invalid. Validating offsets beforehand is verbose and error prone. The commit updates Packet::data() api to take a SliceIndex and always to return an Option. The call-sites are so forced to explicitly handle the case where the offsets are invalid.
1 parent 7c95ae3 commit 5dbf7d8

15 files changed

Lines changed: 151 additions & 120 deletions

File tree

bench-streamer/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ fn producer(addr: &SocketAddr, exit: Arc<AtomicBool>) -> JoinHandle<()> {
3737
for p in packet_batch.iter() {
3838
let a = p.meta.socket_addr();
3939
assert!(p.meta.size <= PACKET_DATA_SIZE);
40-
send.send_to(p.data(), &a).unwrap();
40+
let data = p.data(..).unwrap_or_default();
41+
send.send_to(data, &a).unwrap();
4142
num += 1;
4243
}
4344
assert_eq!(num, 10);

core/src/banking_stage.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ impl BankingStage {
541541
.iter()
542542
.filter_map(|p| {
543543
if !p.meta.forwarded() && data_budget.take(p.meta.size) {
544-
Some(p.data().to_vec())
544+
Some(p.data(..)?.to_vec())
545545
} else {
546546
None
547547
}

core/src/packet_hasher.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl Default for PacketHasher {
2626

2727
impl PacketHasher {
2828
pub(crate) fn hash_packet(&self, packet: &Packet) -> u64 {
29-
self.hash_data(packet.data())
29+
self.hash_data(packet.data(..).unwrap_or_default())
3030
}
3131

3232
pub(crate) fn hash_shred(&self, shred: &Shred) -> u64 {

core/src/serve_repair.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ mod tests {
814814
.into_iter()
815815
.filter_map(|p| {
816816
assert_eq!(repair_response::nonce(p).unwrap(), nonce);
817-
Shred::new_from_serialized_shred(p.data().to_vec()).ok()
817+
Shred::new_from_serialized_shred(p.data(..).unwrap().to_vec()).ok()
818818
})
819819
.collect();
820820
assert!(!rv.is_empty());
@@ -898,7 +898,7 @@ mod tests {
898898
.into_iter()
899899
.filter_map(|p| {
900900
assert_eq!(repair_response::nonce(p).unwrap(), nonce);
901-
Shred::new_from_serialized_shred(p.data().to_vec()).ok()
901+
Shred::new_from_serialized_shred(p.data(..).unwrap().to_vec()).ok()
902902
})
903903
.collect();
904904
assert_eq!(rv[0].index(), 1);
@@ -1347,7 +1347,7 @@ mod tests {
13471347

13481348
fn verify_responses<'a>(request: &ShredRepairType, packets: impl Iterator<Item = &'a Packet>) {
13491349
for packet in packets {
1350-
let shred_payload = packet.data().to_vec();
1350+
let shred_payload = packet.data(..).unwrap().to_vec();
13511351
let shred = Shred::new_from_serialized_shred(shred_payload).unwrap();
13521352
request.verify_response(&shred);
13531353
}

core/src/unprocessed_packet_batches.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,12 +368,14 @@ pub fn deserialize_packets<'a>(
368368

369369
/// Read the transaction message from packet data
370370
pub fn packet_message(packet: &Packet) -> Result<&[u8], DeserializedPacketError> {
371-
let (sig_len, sig_size) =
372-
decode_shortu16_len(packet.data()).map_err(DeserializedPacketError::ShortVecError)?;
371+
let (sig_len, sig_size) = packet
372+
.data(..)
373+
.and_then(|bytes| decode_shortu16_len(bytes).ok())
374+
.ok_or(DeserializedPacketError::ShortVecError(()))?;
373375
sig_len
374376
.checked_mul(size_of::<Signature>())
375377
.and_then(|v| v.checked_add(sig_size))
376-
.and_then(|msg_start| packet.data().get(msg_start..))
378+
.and_then(|msg_start| packet.data(msg_start..))
377379
.ok_or(DeserializedPacketError::SignatureOverflowed(sig_size))
378380
}
379381

core/src/window_service.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ where
363363
inc_new_counter_debug!("streamer-recv_window-invalid_or_unnecessary_packet", 1);
364364
return None;
365365
}
366-
let serialized_shred = packet.data().to_vec();
366+
let serialized_shred = packet.data(..)?.to_vec();
367367
let shred = Shred::new_from_serialized_shred(serialized_shred).ok()?;
368368
if !shred_filter(&shred, working_bank.clone(), last_root) {
369369
return None;

gossip/tests/gossip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ pub fn cluster_info_retransmit() {
260260
let retransmit_peers: Vec<_> = peers.iter().collect();
261261
retransmit_to(
262262
&retransmit_peers,
263-
p.data(),
263+
p.data(..).unwrap(),
264264
&tn1,
265265
false,
266266
&SocketAddrSpace::Unspecified,

ledger/src/shred.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ pub mod layout {
509509
use {super::*, std::ops::Range};
510510

511511
fn get_shred_size(packet: &Packet) -> Option<usize> {
512-
let size = packet.data().len();
512+
let size = packet.data(..)?.len();
513513
if packet.meta.repair() {
514514
size.checked_sub(SIZE_OF_NONCE)
515515
} else {
@@ -519,7 +519,7 @@ pub mod layout {
519519

520520
pub fn get_shred(packet: &Packet) -> Option<&[u8]> {
521521
let size = get_shred_size(packet)?;
522-
let shred = packet.data().get(..size)?;
522+
let shred = packet.data(..size)?;
523523
// Should at least have a signature.
524524
(size >= SIZE_OF_SIGNATURE).then(|| shred)
525525
}
@@ -826,7 +826,7 @@ mod tests {
826826
let shred = Shred::new_from_data(10, 0, 1000, &[1, 2, 3], ShredFlags::empty(), 0, 1, 0);
827827
let mut packet = Packet::default();
828828
shred.copy_to_packet(&mut packet);
829-
let shred_res = Shred::new_from_serialized_shred(packet.data().to_vec());
829+
let shred_res = Shred::new_from_serialized_shred(packet.data(..).unwrap().to_vec());
830830
assert_matches!(
831831
shred.parent(),
832832
Err(Error::InvalidParentOffset {
@@ -1029,9 +1029,12 @@ mod tests {
10291029
assert_eq!(shred, Shred::new_from_serialized_shred(payload).unwrap());
10301030
assert_eq!(
10311031
shred.reference_tick(),
1032-
layout::get_reference_tick(packet.data()).unwrap()
1032+
layout::get_reference_tick(packet.data(..).unwrap()).unwrap()
1033+
);
1034+
assert_eq!(
1035+
layout::get_slot(packet.data(..).unwrap()),
1036+
Some(shred.slot())
10331037
);
1034-
assert_eq!(layout::get_slot(packet.data()), Some(shred.slot()));
10351038
assert_eq!(
10361039
get_shred_slot_index_type(&packet, &mut ShredFetchStats::default()),
10371040
Some((shred.slot(), shred.index(), shred.shred_type()))
@@ -1070,9 +1073,12 @@ mod tests {
10701073
assert_eq!(shred, Shred::new_from_serialized_shred(payload).unwrap());
10711074
assert_eq!(
10721075
shred.reference_tick(),
1073-
layout::get_reference_tick(packet.data()).unwrap()
1076+
layout::get_reference_tick(packet.data(..).unwrap()).unwrap()
1077+
);
1078+
assert_eq!(
1079+
layout::get_slot(packet.data(..).unwrap()),
1080+
Some(shred.slot())
10741081
);
1075-
assert_eq!(layout::get_slot(packet.data()), Some(shred.slot()));
10761082
assert_eq!(
10771083
get_shred_slot_index_type(&packet, &mut ShredFetchStats::default()),
10781084
Some((shred.slot(), shred.index(), shred.shred_type()))
@@ -1116,7 +1122,10 @@ mod tests {
11161122
packet.meta.size = payload.len();
11171123
assert_eq!(shred.bytes_to_store(), payload);
11181124
assert_eq!(shred, Shred::new_from_serialized_shred(payload).unwrap());
1119-
assert_eq!(layout::get_slot(packet.data()), Some(shred.slot()));
1125+
assert_eq!(
1126+
layout::get_slot(packet.data(..).unwrap()),
1127+
Some(shred.slot())
1128+
);
11201129
assert_eq!(
11211130
get_shred_slot_index_type(&packet, &mut ShredFetchStats::default()),
11221131
Some((shred.slot(), shred.index(), shred.shred_type()))

ledger/src/sigverify_shreds.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ fn sign_shred_cpu(keypair: &Keypair, packet: &mut Packet) {
281281
packet.meta.size >= sig.end,
282282
"packet is not large enough for a signature"
283283
);
284-
let signature = keypair.sign_message(&packet.data()[msg]);
284+
let signature = keypair.sign_message(packet.data(msg).unwrap());
285285
trace!("signature {:?}", signature);
286286
packet.buffer_mut()[sig].copy_from_slice(signature.as_ref());
287287
}

0 commit comments

Comments
 (0)