limits pre-allocation size when deserializing shreds (#24921)

Though current Shred struct is not vulnerable to this, adding with_limit
causes pre-allocation size to be limited to prevent against memory
exhaustion attacks:
https://github.com/bincode-org/bincode/blob/2d3f42034/readme.md
This commit is contained in:
behzad nouri 2022-05-03 12:13:45 +00:00 committed by GitHub
parent 59177f0f39
commit 9587c8537f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 6 deletions

View File

@ -59,7 +59,7 @@ use {
num_enum::{IntoPrimitive, TryFromPrimitive},
serde::{Deserialize, Serialize},
solana_entry::entry::{create_ticks, Entry},
solana_perf::packet::{limited_deserialize, Packet},
solana_perf::packet::{deserialize_from_with_limit, limited_deserialize, Packet},
solana_sdk::{
clock::Slot,
hash::{hashv, Hash},
@ -290,16 +290,16 @@ impl Shred {
pub fn new_from_serialized_shred(mut payload: Vec<u8>) -> Result<Self, Error> {
let mut cursor = Cursor::new(&payload[..]);
let common_header: ShredCommonHeader = bincode::deserialize_from(&mut cursor)?;
let common_header: ShredCommonHeader = deserialize_from_with_limit(&mut cursor)?;
let (data_header, coding_header) = match common_header.shred_type {
ShredType::Code => {
let coding_header = bincode::deserialize_from(&mut cursor)?;
let coding_header = deserialize_from_with_limit(&mut cursor)?;
// see: https://github.com/solana-labs/solana/pull/10109
payload.truncate(SHRED_PAYLOAD_SIZE);
(DataShredHeader::default(), coding_header)
}
ShredType::Data => {
let data_header = bincode::deserialize_from(&mut cursor)?;
let data_header = deserialize_from_with_limit(&mut cursor)?;
// see: https://github.com/solana-labs/solana/pull/16602
payload.resize(SHRED_PAYLOAD_SIZE, 0u8);
(data_header, CodingShredHeader::default())

View File

@ -3,8 +3,8 @@ pub use solana_sdk::packet::{Meta, Packet, PacketFlags, PACKET_DATA_SIZE};
use {
crate::{cuda_runtime::PinnedVec, recycler::Recycler},
bincode::config::Options,
serde::Serialize,
std::net::SocketAddr,
serde::{de::DeserializeOwned, Serialize},
std::{io::Read, net::SocketAddr},
};
pub const NUM_PACKETS: usize = 1024 * 8;
@ -137,6 +137,20 @@ where
.deserialize_from(data)
}
pub fn deserialize_from_with_limit<R, T>(reader: R) -> bincode::Result<T>
where
R: Read,
T: DeserializeOwned,
{
// with_limit causes pre-allocation size to be limited
// to prevent against memory exhaustion attacks.
bincode::options()
.with_limit(PACKET_DATA_SIZE as u64)
.with_fixint_encoding()
.allow_trailing_bytes()
.deserialize_from(reader)
}
#[cfg(test)]
mod tests {
use {