From c8770771578eb51b3302f2fc8abcafd214c78b01 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 18 Sep 2023 12:34:45 +0200 Subject: [PATCH 1/3] Validate wasm code in `init_chain` --- apps/src/lib/node/ledger/shell/init_chain.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/src/lib/node/ledger/shell/init_chain.rs b/apps/src/lib/node/ledger/shell/init_chain.rs index b650e2d7309..ceb4e9c4460 100644 --- a/apps/src/lib/node/ledger/shell/init_chain.rs +++ b/apps/src/lib/node/ledger/shell/init_chain.rs @@ -19,6 +19,7 @@ use namada::types::hash::Hash as CodeHash; use namada::types::key::*; use namada::types::time::{DateTimeUtc, TimeZone, Utc}; use namada::types::token; +use namada::vm::validate_untrusted_wasm; use super::*; use crate::facade::tendermint_proto::google::protobuf; @@ -142,6 +143,9 @@ where || tx_whitelist.contains(&code_hash.to_string().to_lowercase()) || vp_whitelist.contains(&code_hash.to_string().to_lowercase()) { + validate_untrusted_wasm(&code) + .map_err(|e| Error::LoadingWasm(e.to_string()))?; + #[cfg(not(test))] if name.starts_with("tx_") { self.tx_wasm_cache.pre_compile(&code); From 95530986217aec7bef031ca2d47f5907d478e1df Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 18 Sep 2023 16:00:48 +0200 Subject: [PATCH 2/3] Adds a client utility to validate wasm code --- apps/src/lib/cli.rs | 47 ++++++++++++++++++++++++++++++++++++ apps/src/lib/cli/client.rs | 3 +++ apps/src/lib/client/utils.rs | 12 +++++++++ 3 files changed, 62 insertions(+) diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index 7ef136bc98c..83e9cee5e10 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -1898,6 +1898,7 @@ pub mod cmds { pub enum Utils { JoinNetwork(JoinNetwork), FetchWasms(FetchWasms), + ValidateWasm(ValidateWasm), InitNetwork(InitNetwork), InitGenesisValidator(InitGenesisValidator), PkToTmAddress(PkToTmAddress), @@ -1913,6 +1914,8 @@ pub mod cmds { let join_network = SubCmd::parse(matches).map(Self::JoinNetwork); let fetch_wasms = SubCmd::parse(matches).map(Self::FetchWasms); + let validate_wasm = + SubCmd::parse(matches).map(Self::ValidateWasm); let init_network = SubCmd::parse(matches).map(Self::InitNetwork); let init_genesis = @@ -1924,6 +1927,7 @@ pub mod cmds { let epoch_sleep = SubCmd::parse(matches).map(Self::EpochSleep); join_network .or(fetch_wasms) + .or(validate_wasm) .or(init_network) .or(init_genesis) .or(pk_to_tm_address) @@ -1937,6 +1941,7 @@ pub mod cmds { .about("Utilities.") .subcommand(JoinNetwork::def()) .subcommand(FetchWasms::def()) + .subcommand(ValidateWasm::def()) .subcommand(InitNetwork::def()) .subcommand(InitGenesisValidator::def()) .subcommand(PkToTmAddress::def()) @@ -1985,6 +1990,28 @@ pub mod cmds { } } + #[derive(Clone, Debug)] + pub struct ValidateWasm(pub args::ValidateWasm); + + impl SubCmd for ValidateWasm { + const CMD: &'static str = "validate-wasm"; + + fn parse(matches: &ArgMatches) -> Option { + matches + .subcommand_matches(Self::CMD) + .map(|matches| Self(args::ValidateWasm::parse(matches))) + } + + fn def() -> App { + App::new(Self::CMD) + .about( + "Check that the provided wasm code is valid by the Namada \ + standards.", + ) + .add_args::() + } + } + #[derive(Clone, Debug)] pub struct InitNetwork(pub args::InitNetwork); @@ -5481,6 +5508,26 @@ pub mod args { } } + #[derive(Clone, Debug)] + pub struct ValidateWasm { + pub code_path: PathBuf, + } + + impl Args for ValidateWasm { + fn parse(matches: &ArgMatches) -> Self { + let code_path = CODE_PATH.parse(matches); + Self { code_path } + } + + fn def(app: App) -> App { + app.arg( + CODE_PATH + .def() + .help("The path to the wasm file to validate."), + ) + } + } + #[derive(Clone, Debug)] pub struct InitNetwork { pub genesis_path: PathBuf, diff --git a/apps/src/lib/cli/client.rs b/apps/src/lib/cli/client.rs index 675c5b4aea4..b0991d8c0d2 100644 --- a/apps/src/lib/cli/client.rs +++ b/apps/src/lib/cli/client.rs @@ -634,6 +634,9 @@ impl CliApi { Utils::FetchWasms(FetchWasms(args)) => { utils::fetch_wasms(global_args, args).await } + Utils::ValidateWasm(ValidateWasm(args)) => { + utils::validate_wasm(args) + } Utils::InitNetwork(InitNetwork(args)) => { utils::init_network(global_args, args) } diff --git a/apps/src/lib/client/utils.rs b/apps/src/lib/client/utils.rs index 77b18f9136f..180f36865c6 100644 --- a/apps/src/lib/client/utils.rs +++ b/apps/src/lib/client/utils.rs @@ -15,6 +15,7 @@ use namada::types::address; use namada::types::chain::ChainId; use namada::types::dec::Dec; use namada::types::key::*; +use namada::vm::validate_untrusted_wasm; use prost::bytes::Bytes; use rand::prelude::ThreadRng; use rand::thread_rng; @@ -363,6 +364,17 @@ pub async fn fetch_wasms_aux(base_dir: &Path, chain_id: &ChainId) { wasm_loader::pre_fetch_wasm(&wasm_dir).await; } +pub fn validate_wasm(args::ValidateWasm { code_path }: args::ValidateWasm) { + let code = std::fs::read(code_path).unwrap(); + match validate_untrusted_wasm(code) { + Ok(()) => println!("Wasm code is valid"), + Err(e) => { + eprintln!("Wasm code is invalid: {e}"); + cli::safe_exit(1) + } + } +} + /// Length of a Tendermint Node ID in bytes const TENDERMINT_NODE_ID_LENGTH: usize = 20; From 06961993141956255031117cc27aa28208c6fec7 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 18 Sep 2023 16:34:37 +0200 Subject: [PATCH 3/3] changelog: add #1902 --- .changelog/unreleased/bug-fixes/1902-validate-wasm.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/bug-fixes/1902-validate-wasm.md diff --git a/.changelog/unreleased/bug-fixes/1902-validate-wasm.md b/.changelog/unreleased/bug-fixes/1902-validate-wasm.md new file mode 100644 index 00000000000..a6c55870007 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1902-validate-wasm.md @@ -0,0 +1,2 @@ +- Added wasm validation in `init_chain` and in client utils. + ([\#1902](https://github.com/anoma/namada/pull/1902)) \ No newline at end of file