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

Bail on all CPI errors (bp #14500) #14507

Merged
merged 1 commit into from
Jan 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions programs/bpf/c/src/invoke/invoke.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ static const uint8_t TEST_CAP_SIGNERS = 7;
static const uint8_t TEST_ALLOC_ACCESS_VIOLATION = 8;
static const uint8_t TEST_INSTRUCTION_DATA_TOO_LARGE = 9;
static const uint8_t TEST_INSTRUCTION_META_TOO_LARGE = 10;
static const uint8_t TEST_RETURN_ERROR = 11;

static const int MINT_INDEX = 0;
static const int ARGUMENT_INDEX = 1;
Expand Down Expand Up @@ -112,7 +113,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
{accounts[INVOKED_ARGUMENT_INDEX].key, true, true},
{accounts[INVOKED_PROGRAM_INDEX].key, false, false},
{accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false}};
uint8_t data[] = {TEST_VERIFY_TRANSLATIONS, 1, 2, 3, 4, 5};
uint8_t data[] = {VERIFY_TRANSLATIONS, 1, 2, 3, 4, 5};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
Expand All @@ -133,18 +134,6 @@ extern uint64_t entrypoint(const uint8_t *input) {
sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts)));
}

sol_log("Test return error");
{
SolAccountMeta arguments[] = {{accounts[ARGUMENT_INDEX].key, true, true}};
uint8_t data[] = {TEST_RETURN_ERROR};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};

sol_assert(42 ==
sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts)));
}

sol_log("Test create_program_address");
{
uint8_t seed1[] = {'Y', 'o', 'u', ' ', 'p', 'a', 's', 's',
Expand Down Expand Up @@ -183,7 +172,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
{accounts[DERIVED_KEY1_INDEX].key, true, true},
{accounts[DERIVED_KEY2_INDEX].key, true, false},
{accounts[DERIVED_KEY3_INDEX].key, false, false}};
uint8_t data[] = {TEST_DERIVED_SIGNERS, bump_seed2, bump_seed3};
uint8_t data[] = {DERIVED_SIGNERS, bump_seed2, bump_seed3};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
Expand All @@ -202,7 +191,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
{
SolAccountMeta arguments[] = {
{accounts[INVOKED_ARGUMENT_INDEX].key, true, false}};
uint8_t data[] = {TEST_VERIFY_WRITER};
uint8_t data[] = {VERIFY_WRITER};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
Expand All @@ -222,7 +211,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
{accounts[INVOKED_ARGUMENT_INDEX].key, true, true},
{accounts[ARGUMENT_INDEX].key, true, true},
{accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false}};
uint8_t data[] = {TEST_NESTED_INVOKE};
uint8_t data[] = {NESTED_INVOKE};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
Expand Down Expand Up @@ -252,7 +241,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
sol_log("Test privilege escalation signer");
SolAccountMeta arguments[] = {
{accounts[DERIVED_KEY3_INDEX].key, false, false}};
uint8_t data[] = {TEST_VERIFY_PRIVILEGE_ESCALATION};
uint8_t data[] = {VERIFY_PRIVILEGE_ESCALATION};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
Expand All @@ -268,7 +257,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
sol_log("Test privilege escalation writable");
SolAccountMeta arguments[] = {
{accounts[DERIVED_KEY3_INDEX].key, false, false}};
uint8_t data[] = {TEST_VERIFY_PRIVILEGE_ESCALATION};
uint8_t data[] = {VERIFY_PRIVILEGE_ESCALATION};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
Expand All @@ -284,7 +273,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
sol_log("Test program not executable");
SolAccountMeta arguments[] = {
{accounts[DERIVED_KEY3_INDEX].key, false, false}};
uint8_t data[] = {TEST_VERIFY_PRIVILEGE_ESCALATION};
uint8_t data[] = {VERIFY_PRIVILEGE_ESCALATION};
const SolInstruction instruction = {accounts[ARGUMENT_INDEX].key, arguments,
SOL_ARRAY_SIZE(arguments), data,
SOL_ARRAY_SIZE(data)};
Expand Down Expand Up @@ -437,6 +426,16 @@ extern uint64_t entrypoint(const uint8_t *input) {

break;
}
case TEST_RETURN_ERROR: {
SolAccountMeta arguments[] = {{accounts[ARGUMENT_INDEX].key, true, true}};
uint8_t data[] = {RETURN_ERROR};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};

sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts));
break;
}
default:
sol_panic();
}
Expand Down
15 changes: 8 additions & 7 deletions programs/bpf/c/src/invoked/instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

#include <solana_sdk.h>

const uint8_t TEST_VERIFY_TRANSLATIONS = 0;
const uint8_t TEST_RETURN_ERROR = 1;
const uint8_t TEST_DERIVED_SIGNERS = 2;
const uint8_t TEST_VERIFY_NESTED_SIGNERS = 3;
const uint8_t TEST_VERIFY_WRITER = 4;
const uint8_t TEST_VERIFY_PRIVILEGE_ESCALATION = 5;
const uint8_t TEST_NESTED_INVOKE = 6;
const uint8_t VERIFY_TRANSLATIONS = 0;
const uint8_t RETURN_ERROR = 1;
const uint8_t DERIVED_SIGNERS = 2;
const uint8_t VERIFY_NESTED_SIGNERS = 3;
const uint8_t VERIFY_WRITER = 4;
const uint8_t VERIFY_PRIVILEGE_ESCALATION = 5;
const uint8_t NESTED_INVOKE = 6;
const uint8_t RETURN_OK = 7;
22 changes: 13 additions & 9 deletions programs/bpf/c/src/invoked/invoked.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
}

switch (params.data[0]) {
case TEST_VERIFY_TRANSLATIONS: {
case VERIFY_TRANSLATIONS: {
sol_log("verify data translations");

static const int ARGUMENT_INDEX = 0;
Expand Down Expand Up @@ -85,11 +85,15 @@ extern uint64_t entrypoint(const uint8_t *input) {
accounts[INVOKED_PROGRAM_DUP_INDEX].executable);
break;
}
case TEST_RETURN_ERROR: {
case RETURN_OK: {
sol_log("return Ok");
return SUCCESS;
}
case RETURN_ERROR: {
sol_log("return error");
return 42;
}
case TEST_DERIVED_SIGNERS: {
case DERIVED_SIGNERS: {
sol_log("verify derived signers");
static const int INVOKED_PROGRAM_INDEX = 0;
static const int DERIVED_KEY1_INDEX = 1;
Expand All @@ -108,7 +112,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
{accounts[DERIVED_KEY1_INDEX].key, true, false},
{accounts[DERIVED_KEY2_INDEX].key, true, true},
{accounts[DERIVED_KEY3_INDEX].key, false, true}};
uint8_t data[] = {TEST_VERIFY_NESTED_SIGNERS};
uint8_t data[] = {VERIFY_NESTED_SIGNERS};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
Expand All @@ -130,7 +134,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
break;
}

case TEST_VERIFY_NESTED_SIGNERS: {
case VERIFY_NESTED_SIGNERS: {
sol_log("verify derived nested signers");
static const int DERIVED_KEY1_INDEX = 0;
static const int DERIVED_KEY2_INDEX = 1;
Expand All @@ -144,19 +148,19 @@ extern uint64_t entrypoint(const uint8_t *input) {
break;
}

case TEST_VERIFY_WRITER: {
case VERIFY_WRITER: {
sol_log("verify writable");
static const int ARGUMENT_INDEX = 0;
sol_assert(sol_deserialize(input, &params, 1));

sol_assert(accounts[ARGUMENT_INDEX].is_writable);
break;
}
case TEST_VERIFY_PRIVILEGE_ESCALATION: {
case VERIFY_PRIVILEGE_ESCALATION: {
sol_log("Success");
break;
}
case TEST_NESTED_INVOKE: {
case NESTED_INVOKE: {
sol_log("invoke");

static const int INVOKED_ARGUMENT_INDEX = 0;
Expand All @@ -179,7 +183,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
SolAccountMeta arguments[] = {
{accounts[INVOKED_ARGUMENT_INDEX].key, true, true},
{accounts[ARGUMENT_INDEX].key, true, true}};
uint8_t data[] = {TEST_NESTED_INVOKE};
uint8_t data[] = {NESTED_INVOKE};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
Expand Down
64 changes: 21 additions & 43 deletions programs/bpf/rust/invoke/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const TEST_CAP_SIGNERS: u8 = 7;
const TEST_ALLOC_ACCESS_VIOLATION: u8 = 8;
const TEST_INSTRUCTION_DATA_TOO_LARGE: u8 = 9;
const TEST_INSTRUCTION_META_TOO_LARGE: u8 = 10;
const TEST_RETURN_ERROR: u8 = 11;

// const MINT_INDEX: usize = 0;
const ARGUMENT_INDEX: usize = 1;
Expand Down Expand Up @@ -122,7 +123,7 @@ fn process_instruction(
(accounts[INVOKED_PROGRAM_INDEX].key, false, false),
(accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false),
],
vec![TEST_VERIFY_TRANSLATIONS, 1, 2, 3, 4, 5],
vec![VERIFY_TRANSLATIONS, 1, 2, 3, 4, 5],
);
invoke(&instruction, accounts)?;
}
Expand All @@ -137,29 +138,6 @@ fn process_instruction(
invoke(&instruction, accounts)?;
}

msg!("Test return error");
{
assert_eq!(
10,
**accounts[INVOKED_ARGUMENT_INDEX].try_borrow_lamports()?
);
assert_eq!(0, accounts[INVOKED_ARGUMENT_INDEX].try_borrow_data()?[0]);
let instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[(accounts[INVOKED_ARGUMENT_INDEX].key, false, true)],
vec![TEST_RETURN_ERROR],
);
assert_eq!(
invoke(&instruction, accounts),
Err(ProgramError::Custom(42))
);
assert_eq!(
10,
**accounts[INVOKED_ARGUMENT_INDEX].try_borrow_lamports()?
);
assert_eq!(0, accounts[INVOKED_ARGUMENT_INDEX].try_borrow_data()?[0]);
}

msg!("Test refcell usage");
{
let writable = INVOKED_ARGUMENT_INDEX;
Expand All @@ -171,14 +149,11 @@ fn process_instruction(
(accounts[writable].key, true, true),
(accounts[readable].key, false, false),
],
vec![TEST_RETURN_ERROR, 1, 2, 3, 4, 5],
vec![RETURN_OK, 1, 2, 3, 4, 5],
);

// success with this account configuration as a check
assert_eq!(
invoke(&instruction, accounts),
Err(ProgramError::Custom(42))
);
invoke(&instruction, accounts)?;

{
// writable but lamports borrow_mut'd
Expand Down Expand Up @@ -231,18 +206,12 @@ fn process_instruction(
{
// readable but lamports borrow'd
let _ref_mut = accounts[readable].try_borrow_lamports()?;
assert_eq!(
invoke(&instruction, accounts),
Err(ProgramError::Custom(42))
);
invoke(&instruction, accounts)?;
}
{
// readable but data borrow'd
let _ref_mut = accounts[readable].try_borrow_data()?;
assert_eq!(
invoke(&instruction, accounts),
Err(ProgramError::Custom(42))
);
invoke(&instruction, accounts)?;
}
}

Expand Down Expand Up @@ -289,7 +258,7 @@ fn process_instruction(
(accounts[DERIVED_KEY2_INDEX].key, true, false),
(accounts[DERIVED_KEY3_INDEX].key, false, false),
],
vec![TEST_DERIVED_SIGNERS, bump_seed2, bump_seed3],
vec![DERIVED_SIGNERS, bump_seed2, bump_seed3],
);
invoke_signed(
&invoked_instruction,
Expand All @@ -303,7 +272,7 @@ fn process_instruction(
let invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[(accounts[ARGUMENT_INDEX].key, false, true)],
vec![TEST_VERIFY_WRITER],
vec![VERIFY_WRITER],
);
invoke(&invoked_instruction, accounts)?;
}
Expand All @@ -324,7 +293,7 @@ fn process_instruction(
(accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false),
(accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false),
],
vec![TEST_NESTED_INVOKE],
vec![NESTED_INVOKE],
);
invoke(&instruction, accounts)?;
msg!("2nd invoke from first program");
Expand Down Expand Up @@ -354,7 +323,7 @@ fn process_instruction(
let mut invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[(accounts[DERIVED_KEY3_INDEX].key, false, false)],
vec![TEST_VERIFY_PRIVILEGE_ESCALATION],
vec![VERIFY_PRIVILEGE_ESCALATION],
);
invoke(&invoked_instruction, accounts)?;

Expand All @@ -367,7 +336,7 @@ fn process_instruction(
let mut invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[(accounts[DERIVED_KEY3_INDEX].key, false, false)],
vec![TEST_VERIFY_PRIVILEGE_ESCALATION],
vec![VERIFY_PRIVILEGE_ESCALATION],
);
invoke(&invoked_instruction, accounts)?;

Expand All @@ -381,7 +350,7 @@ fn process_instruction(
let instruction = create_instruction(
*accounts[ARGUMENT_INDEX].key,
&[(accounts[ARGUMENT_INDEX].key, true, true)],
vec![TEST_RETURN_ERROR],
vec![RETURN_OK],
);
invoke(&instruction, accounts)?;
}
Expand Down Expand Up @@ -514,6 +483,15 @@ fn process_instruction(
);
invoke_signed(&instruction, &[], &[])?;
}
TEST_RETURN_ERROR => {
msg!("Test return error");
let instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[(accounts[INVOKED_ARGUMENT_INDEX].key, false, true)],
vec![RETURN_ERROR],
);
let _ = invoke(&instruction, accounts);
}
_ => panic!(),
}

Expand Down
15 changes: 8 additions & 7 deletions programs/bpf/rust/invoked/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ use solana_program::{
pubkey::Pubkey,
};

pub const TEST_VERIFY_TRANSLATIONS: u8 = 0;
pub const TEST_RETURN_ERROR: u8 = 1;
pub const TEST_DERIVED_SIGNERS: u8 = 2;
pub const TEST_VERIFY_NESTED_SIGNERS: u8 = 3;
pub const TEST_VERIFY_WRITER: u8 = 4;
pub const TEST_VERIFY_PRIVILEGE_ESCALATION: u8 = 5;
pub const TEST_NESTED_INVOKE: u8 = 6;
pub const VERIFY_TRANSLATIONS: u8 = 0;
pub const RETURN_ERROR: u8 = 1;
pub const DERIVED_SIGNERS: u8 = 2;
pub const VERIFY_NESTED_SIGNERS: u8 = 3;
pub const VERIFY_WRITER: u8 = 4;
pub const VERIFY_PRIVILEGE_ESCALATION: u8 = 5;
pub const NESTED_INVOKE: u8 = 6;
pub const RETURN_OK: u8 = 7;

pub fn create_instruction(
program_id: Pubkey,
Expand Down
Loading