Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more limits on length on object from the outside world. #4301

Merged
merged 9 commits into from
Aug 1, 2023
4 changes: 4 additions & 0 deletions massa-execution-exports/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ pub struct ExecutionConfig {
pub stats_time_window_duration: MassaTime,
/// Max miss ratio for auto roll sell
pub max_miss_ratio: Ratio<u64>,
/// Max function length in call sc
pub max_function_length: u16,
/// Max parameter length in call sc
pub max_parameter_length: u32,
/// Max size of a datastore key
pub max_datastore_key_length: u8,
/// Max bytecode size
Expand Down
4 changes: 3 additions & 1 deletion massa-execution-exports/src/test_exports/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ impl Default for ExecutionConfig {
denunciation_expire_periods: DENUNCIATION_EXPIRE_PERIODS,
broadcast_enabled: true,
broadcast_slot_execution_output_channel_capacity: 5000,
max_event_size: 102_400,
max_event_size: 50_000,
max_function_length: 1000,
max_parameter_length: 1000,
}
}
}
1 change: 1 addition & 0 deletions massa-execution-worker/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ impl ExecutionState {
lru_cache_size: config.lru_cache_size,
hd_cache_size: config.hd_cache_size,
snip_amount: config.snip_amount,
max_module_length: config.max_bytecode_size,
})));

// Create an empty placeholder execution context, with shared atomic access
Expand Down
15 changes: 12 additions & 3 deletions massa-execution-worker/src/interface_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ impl InterfaceImpl {
lru_cache_size: config.lru_cache_size,
hd_cache_size: config.hd_cache_size,
snip_amount: config.snip_amount,
max_module_length: config.max_bytecode_size,
})));
let vesting_manager = Arc::new(
crate::vesting_manager::VestingManager::new(
Expand Down Expand Up @@ -1134,7 +1135,7 @@ impl Interface for InterfaceImpl {
///
/// # Arguments
/// * `target_address`: Destination address hash in format string
/// * `target_handler`: Name of the message handling function
/// * `target_function`: Name of the message handling function
/// * `validity_start`: Tuple containing the period and thread of the validity start slot
/// * `validity_end`: Tuple containing the period and thread of the validity end slot
/// * `max_gas`: Maximum gas for the message execution
Expand All @@ -1144,7 +1145,7 @@ impl Interface for InterfaceImpl {
fn send_message(
&self,
target_address: &str,
target_handler: &str,
target_function: &str,
validity_start: (u64, u8),
validity_end: (u64, u8),
max_gas: u64,
Expand All @@ -1166,6 +1167,14 @@ impl Interface for InterfaceImpl {
bail!("target address is not a smart contract address")
}

// Length verifications
if target_function.len() > self.config.max_function_length as usize {
bail!("Function name is too large");
}
if data.len() > self.config.max_parameter_length as usize {
bail!("Parameter size is too large");
}

let mut execution_context = context_guard!(self);
let emission_slot = execution_context.slot;
let emission_index = execution_context.created_message_index;
Expand All @@ -1179,7 +1188,7 @@ impl Interface for InterfaceImpl {
emission_index,
sender,
target_addr,
target_handler.to_string(),
target_function.to_string(),
max_gas,
fee,
coins,
Expand Down
48 changes: 43 additions & 5 deletions massa-ledger-worker/src/ledger_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub struct LedgerDB {
amount_deserializer: AmountDeserializer,
bytecode_deserializer: BytecodeDeserializer,
max_datastore_value_length: u64,
max_datastore_key_length: u8,
}

impl Debug for LedgerDB {
Expand Down Expand Up @@ -98,6 +99,7 @@ impl LedgerDB {
Bound::Included(u64::MAX),
),
max_datastore_value_length,
max_datastore_key_length,
}
}

Expand Down Expand Up @@ -310,11 +312,29 @@ impl LedgerDB {
db.put_or_update_entry_value(batch, serialized_key, &bytes_bytecode);

// datastore
for (hash, entry) in ledger_entry.datastore {
for (key, entry) in ledger_entry.datastore {
damip marked this conversation as resolved.
Show resolved Hide resolved
if entry.len() > self.max_datastore_value_length as usize {
panic!(
"Datastore entry for address {} and key {:?} is too big ({} > {})",
addr,
key,
entry.len(),
self.max_datastore_value_length
);
}
if key.len() > self.max_datastore_key_length as usize {
panic!(
"Datastore key for address {} and key {:?} is too big ({} > {})",
addr,
key,
key.len(),
self.max_datastore_key_length
);
}
let mut serialized_key = Vec::new();
self.key_serializer_db
.serialize(
&Key::new(addr, KeyType::DATASTORE(hash)),
&Key::new(addr, KeyType::DATASTORE(key)),
&mut serialized_key,
)
.expect(KEY_SER_ERROR);
Expand Down Expand Up @@ -360,18 +380,36 @@ impl LedgerDB {
}

// datastore
for (hash, update) in entry_update.datastore {
for (key, update) in entry_update.datastore {
if key.len() > self.max_datastore_key_length as usize {
panic!(
"Datastore key for address {} and key {:?} is too big ({} > {})",
addr,
key,
key.len(),
self.max_datastore_key_length
);
}
let mut serialized_key = Vec::new();
self.key_serializer_db
.serialize(
&Key::new(addr, KeyType::DATASTORE(hash)),
&Key::new(addr, KeyType::DATASTORE(key)),
&mut serialized_key,
)
.expect(KEY_SER_ERROR);

damip marked this conversation as resolved.
Show resolved Hide resolved
match update {
SetOrDelete::Set(entry) => {
db.put_or_update_entry_value(batch, serialized_key, &entry)
if entry.len() > self.max_datastore_value_length as usize {
panic!(
"Datastore entry for address {} is too big ({} > {})",
addr,
entry.len(),
self.max_datastore_value_length
);
} else {
db.put_or_update_entry_value(batch, serialized_key, &entry);
}
}
SetOrDelete::Delete => db.delete_key(batch, serialized_key),
}
Expand Down
2 changes: 1 addition & 1 deletion massa-models/src/config/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ pub const MAX_GAS_PER_BLOCK: u64 = u32::MAX as u64;
/// Maximum of GAS allowed for asynchronous messages execution on one slot
pub const MAX_ASYNC_GAS: u64 = 1_000_000_000;
/// Maximum event size in bytes
pub const MAX_EVENT_SIZE: usize = 100 * 1024;
pub const MAX_EVENT_DATA_SIZE: usize = 50_000;

//
// Constants used in network
Expand Down
2 changes: 2 additions & 0 deletions massa-module-cache/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ pub struct ModuleCacheConfig {
pub hd_cache_size: usize,
/// Amount of entries removed when `hd_cache_size` is reached
pub snip_amount: usize,
/// Maximum length of a module
pub max_module_length: u64,
}
10 changes: 9 additions & 1 deletion massa-module-cache/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use massa_hash::Hash;
use massa_models::prehash::BuildHashMapper;
use massa_sc_runtime::{Compiler, RuntimeModule};
use schnellru::{ByLength, LruMap};
use tracing::{debug, warn};
use tracing::{debug, log::info, warn};

use crate::{
config::ModuleCacheConfig, error::CacheError, hd_cache::HDCache, lru_cache::LRUCache,
Expand Down Expand Up @@ -94,6 +94,14 @@ impl ModuleCache {

/// Load a cached module for execution
fn load_module_info(&mut self, bytecode: &[u8]) -> ModuleInfo {
if bytecode.len() > self.cfg.max_module_length as usize {
info!(
"load_module: bytecode length {} exceeds max module length {}",
bytecode.len(),
self.cfg.max_module_length
);
return ModuleInfo::Invalid;
}
let hash = Hash::compute_from(bytecode);
if let Some(lru_module_info) = self.lru_cache.get(hash) {
debug!("load_module: {} present in lru", hash);
Expand Down
6 changes: 4 additions & 2 deletions massa-node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ use massa_models::config::constants::{
VERSION,
};
use massa_models::config::{
MAX_BOOTSTRAPPED_NEW_ELEMENTS, MAX_EVENT_SIZE, MAX_MESSAGE_SIZE,
MAX_BOOTSTRAPPED_NEW_ELEMENTS, MAX_EVENT_DATA_SIZE, MAX_MESSAGE_SIZE,
POOL_CONTROLLER_DENUNCIATIONS_CHANNEL_SIZE, POOL_CONTROLLER_ENDORSEMENTS_CHANNEL_SIZE,
POOL_CONTROLLER_OPERATIONS_CHANNEL_SIZE,
};
Expand Down Expand Up @@ -502,7 +502,9 @@ async fn launch(
broadcast_slot_execution_output_channel_capacity: SETTINGS
.execution
.broadcast_slot_execution_output_channel_capacity,
max_event_size: MAX_EVENT_SIZE,
max_event_size: MAX_EVENT_DATA_SIZE,
max_function_length: MAX_FUNCTION_NAME_LENGTH,
max_parameter_length: MAX_PARAMETERS_SIZE,
};

let execution_channels = ExecutionChannels {
Expand Down