From efcb5cd9f048bf5a1e2846a63453a77986ae0fc8 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 3 Oct 2020 01:58:27 +0000 Subject: [PATCH] Fix zero-len slice translations (#12642) (#12656) (cherry picked from commit d0aa8a6446f8f964cc34037ae67d1508a532546b) Co-authored-by: Jack May --- programs/bpf/c/src/invoke/invoke.c | 12 ++++++++++++ programs/bpf/c/src/invoked/invoked.c | 4 ++++ programs/bpf/rust/invoke/src/lib.rs | 10 ++++++++++ programs/bpf/rust/invoked/src/lib.rs | 4 ++++ programs/bpf/tests/programs.rs | 1 + programs/bpf_loader/src/syscalls.rs | 17 +++++++++++++++++ 6 files changed, 48 insertions(+) diff --git a/programs/bpf/c/src/invoke/invoke.c b/programs/bpf/c/src/invoke/invoke.c index 0c8927b0b455c4..2318b962e20842 100644 --- a/programs/bpf/c/src/invoke/invoke.c +++ b/programs/bpf/c/src/invoke/invoke.c @@ -115,6 +115,18 @@ extern uint64_t entrypoint(const uint8_t *input) { sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts))); } + sol_log("Test no instruction data"); + { + SolAccountMeta arguments[] = {{accounts[ARGUMENT_INDEX].key, true, true}}; + uint8_t data[] = {}; + const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key, + arguments, SOL_ARRAY_SIZE(arguments), + data, SOL_ARRAY_SIZE(data)}; + + sol_assert(SUCCESS == + sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts))); + } + sol_log("Test return error"); { SolAccountMeta arguments[] = {{accounts[ARGUMENT_INDEX].key, true, true}}; diff --git a/programs/bpf/c/src/invoked/invoked.c b/programs/bpf/c/src/invoked/invoked.c index 2da8f8c5e71672..b70b71f6de5a2d 100644 --- a/programs/bpf/c/src/invoked/invoked.c +++ b/programs/bpf/c/src/invoked/invoked.c @@ -12,6 +12,10 @@ extern uint64_t entrypoint(const uint8_t *input) { return ERROR_INVALID_ARGUMENT; } + if (params.data_len == 0) { + return SUCCESS; + } + switch (params.data[0]) { case TEST_VERIFY_TRANSLATIONS: { sol_log("verify data translations"); diff --git a/programs/bpf/rust/invoke/src/lib.rs b/programs/bpf/rust/invoke/src/lib.rs index 4fd842cc1ca6ae..eac71a6d099454 100644 --- a/programs/bpf/rust/invoke/src/lib.rs +++ b/programs/bpf/rust/invoke/src/lib.rs @@ -117,6 +117,16 @@ fn process_instruction( invoke(&instruction, accounts)?; } + info!("Test no instruction data"); + { + let instruction = create_instruction( + *accounts[INVOKED_PROGRAM_INDEX].key, + &[(accounts[ARGUMENT_INDEX].key, true, true)], + vec![], + ); + invoke(&instruction, accounts)?; + } + info!("Test return error"); { let instruction = create_instruction( diff --git a/programs/bpf/rust/invoked/src/lib.rs b/programs/bpf/rust/invoked/src/lib.rs index ca88c135ba1e29..d3495ec0f95122 100644 --- a/programs/bpf/rust/invoked/src/lib.rs +++ b/programs/bpf/rust/invoked/src/lib.rs @@ -21,6 +21,10 @@ fn process_instruction( ) -> ProgramResult { info!("Invoked program"); + if instruction_data.is_empty() { + return Ok(()); + } + match instruction_data[0] { TEST_VERIFY_TRANSLATIONS => { info!("verify data translations"); diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index d68f0aa1956619..8b867d35555c57 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -534,6 +534,7 @@ fn test_program_bpf_invoke() { invoked_program_id.clone(), invoked_program_id.clone(), invoked_program_id.clone(), + invoked_program_id.clone(), ] ); diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 8feb1c3ae121c8..afd47b92e1e1b1 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -213,6 +213,8 @@ macro_rules! translate_slice_mut { && ($vm_addr as u64 as *mut $t).align_offset(align_of::<$t>()) != 0 { Err(SyscallError::UnalignedPointer.into()) + } else if $len == 0 { + Ok(unsafe { from_raw_parts_mut(0x1 as *mut $t, $len as usize) }) } else { match translate_addr::( $vm_addr as u64, @@ -1179,6 +1181,21 @@ mod tests { #[test] fn test_translate_slice() { + // zero len + let good_data = vec![1u8, 2, 3, 4, 5]; + let data: Vec = vec![]; + assert_eq!(0x1 as *const u8, data.as_ptr()); + let addr = good_data.as_ptr() as *const _ as u64; + let regions = vec![MemoryRegion { + addr_host: addr, + addr_vm: 100, + len: good_data.len() as u64, + }]; + let translated_data = + translate_slice!(u8, data.as_ptr(), data.len(), ®ions, &bpf_loader::id()).unwrap(); + assert_eq!(data, translated_data); + assert_eq!(0, translated_data.len()); + // u8 let mut data = vec![1u8, 2, 3, 4, 5]; let addr = data.as_ptr() as *const _ as u64;