Cap CPI signers (#14021)
This commit is contained in:
parent
e1872a450a
commit
e1a4251b07
|
@ -10,6 +10,7 @@ static const uint8_t TEST_PRIVILEGE_ESCALATION_WRITABLE = 3;
|
|||
static const uint8_t TEST_PPROGRAM_NOT_EXECUTABLE = 4;
|
||||
static const uint8_t TEST_EMPTY_ACCOUNTS_SLICE = 5;
|
||||
static const uint8_t TEST_CAP_SEEDS = 6;
|
||||
static const uint8_t TEST_CAP_SIGNERS = 7;
|
||||
|
||||
static const int MINT_INDEX = 0;
|
||||
static const int ARGUMENT_INDEX = 1;
|
||||
|
@ -285,7 +286,6 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
|||
}
|
||||
case TEST_CAP_SEEDS: {
|
||||
sol_log("Test cap seeds");
|
||||
{
|
||||
SolAccountMeta arguments[] = {};
|
||||
uint8_t data[] = {};
|
||||
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
|
||||
|
@ -304,11 +304,48 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
|||
{seed, SOL_ARRAY_SIZE(seed)},
|
||||
};
|
||||
const SolSignerSeeds signers_seeds[] = {{seeds, SOL_ARRAY_SIZE(seeds)}};
|
||||
sol_assert(SUCCESS == sol_invoke_signed(&instruction, accounts,
|
||||
SOL_ARRAY_SIZE(accounts),
|
||||
signers_seeds,
|
||||
SOL_ARRAY_SIZE(signers_seeds)));
|
||||
sol_assert(SUCCESS == sol_invoke_signed(
|
||||
&instruction, accounts, SOL_ARRAY_SIZE(accounts),
|
||||
signers_seeds, SOL_ARRAY_SIZE(signers_seeds)));
|
||||
}
|
||||
case TEST_CAP_SIGNERS: {
|
||||
sol_log("Test cap signers");
|
||||
SolAccountMeta arguments[] = {};
|
||||
uint8_t data[] = {};
|
||||
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
|
||||
arguments, SOL_ARRAY_SIZE(arguments),
|
||||
data, SOL_ARRAY_SIZE(data)};
|
||||
uint8_t seed[] = {"seed"};
|
||||
const SolSignerSeed seed1[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed2[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed3[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed4[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed5[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed6[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed7[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed8[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed9[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed10[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed11[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed12[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed13[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed14[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed15[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed16[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeed seed17[] = {{seed, SOL_ARRAY_SIZE(seed)}};
|
||||
const SolSignerSeeds signers_seeds[] = {
|
||||
{seed1, SOL_ARRAY_SIZE(seed1)}, {seed2, SOL_ARRAY_SIZE(seed2)},
|
||||
{seed3, SOL_ARRAY_SIZE(seed3)}, {seed4, SOL_ARRAY_SIZE(seed4)},
|
||||
{seed5, SOL_ARRAY_SIZE(seed5)}, {seed6, SOL_ARRAY_SIZE(seed6)},
|
||||
{seed7, SOL_ARRAY_SIZE(seed7)}, {seed8, SOL_ARRAY_SIZE(seed8)},
|
||||
{seed9, SOL_ARRAY_SIZE(seed9)}, {seed10, SOL_ARRAY_SIZE(seed10)},
|
||||
{seed11, SOL_ARRAY_SIZE(seed11)}, {seed12, SOL_ARRAY_SIZE(seed12)},
|
||||
{seed13, SOL_ARRAY_SIZE(seed13)}, {seed14, SOL_ARRAY_SIZE(seed14)},
|
||||
{seed15, SOL_ARRAY_SIZE(seed15)}, {seed16, SOL_ARRAY_SIZE(seed16)},
|
||||
{seed17, SOL_ARRAY_SIZE(seed17)}};
|
||||
sol_assert(SUCCESS == sol_invoke_signed(
|
||||
&instruction, accounts, SOL_ARRAY_SIZE(accounts),
|
||||
signers_seeds, SOL_ARRAY_SIZE(signers_seeds)));
|
||||
}
|
||||
default:
|
||||
sol_panic();
|
||||
|
|
|
@ -22,6 +22,7 @@ const TEST_PRIVILEGE_ESCALATION_WRITABLE: u8 = 3;
|
|||
const TEST_PPROGRAM_NOT_EXECUTABLE: u8 = 4;
|
||||
const TEST_EMPTY_ACCOUNTS_SLICE: u8 = 5;
|
||||
const TEST_CAP_SEEDS: u8 = 6;
|
||||
const TEST_CAP_SIGNERS: u8 = 7;
|
||||
|
||||
// const MINT_INDEX: usize = 0;
|
||||
const ARGUMENT_INDEX: usize = 1;
|
||||
|
@ -385,6 +386,33 @@ fn process_instruction(
|
|||
]],
|
||||
)?;
|
||||
}
|
||||
TEST_CAP_SIGNERS => {
|
||||
msg!("Test program max signers");
|
||||
let instruction = create_instruction(*accounts[INVOKED_PROGRAM_INDEX].key, &[], vec![]);
|
||||
invoke_signed(
|
||||
&instruction,
|
||||
accounts,
|
||||
&[
|
||||
&[b"1"],
|
||||
&[b"2"],
|
||||
&[b"3"],
|
||||
&[b"4"],
|
||||
&[b"5"],
|
||||
&[b"6"],
|
||||
&[b"7"],
|
||||
&[b"8"],
|
||||
&[b"9"],
|
||||
&[b"0"],
|
||||
&[b"1"],
|
||||
&[b"2"],
|
||||
&[b"3"],
|
||||
&[b"4"],
|
||||
&[b"5"],
|
||||
&[b"6"],
|
||||
&[b"7"],
|
||||
],
|
||||
)?;
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
|
||||
|
|
|
@ -24,12 +24,10 @@ use solana_sdk::{
|
|||
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
||||
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
|
||||
keyed_account::KeyedAccount,
|
||||
loader_instruction,
|
||||
message::Message,
|
||||
process_instruction::{BpfComputeBudget, InvokeContext, MockInvokeContext},
|
||||
process_instruction::{InvokeContext, MockInvokeContext},
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
system_instruction,
|
||||
sysvar::{clock, fees, rent, slot_hashes, stake_history},
|
||||
transaction::{Transaction, TransactionError},
|
||||
};
|
||||
|
@ -71,6 +69,7 @@ fn read_bpf_program(name: &str) -> Vec<u8> {
|
|||
elf
|
||||
}
|
||||
|
||||
#[cfg(feature = "bpf_rust")]
|
||||
fn write_bpf_program(
|
||||
bank_client: &BankClient,
|
||||
loader_id: &Pubkey,
|
||||
|
@ -78,6 +77,8 @@ fn write_bpf_program(
|
|||
program_keypair: &Keypair,
|
||||
elf: &[u8],
|
||||
) {
|
||||
use solana_sdk::loader_instruction;
|
||||
|
||||
let chunk_size = 256; // Size of chunk just needs to fit into tx
|
||||
let mut offset = 0;
|
||||
for chunk in elf.chunks(chunk_size) {
|
||||
|
@ -522,6 +523,7 @@ fn test_program_bpf_invoke() {
|
|||
const TEST_PPROGRAM_NOT_EXECUTABLE: u8 = 4;
|
||||
const TEST_EMPTY_ACCOUNTS_SLICE: u8 = 5;
|
||||
const TEST_CAP_SEEDS: u8 = 6;
|
||||
const TEST_CAP_SIGNERS: u8 = 7;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
|
@ -823,6 +825,33 @@ fn test_program_bpf_invoke() {
|
|||
TransactionError::InstructionError(0, InstructionError::MaxSeedLengthExceeded)
|
||||
);
|
||||
|
||||
let instruction = Instruction::new(
|
||||
invoke_program_id,
|
||||
&[TEST_CAP_SIGNERS, bump_seed1, bump_seed2, bump_seed3],
|
||||
account_metas.clone(),
|
||||
);
|
||||
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
||||
let tx = Transaction::new(
|
||||
&[
|
||||
&mint_keypair,
|
||||
&argument_keypair,
|
||||
&invoked_argument_keypair,
|
||||
&from_keypair,
|
||||
],
|
||||
message.clone(),
|
||||
bank.last_blockhash(),
|
||||
);
|
||||
let (result, inner_instructions) = process_transaction_and_record_inner(&bank, tx);
|
||||
let invoked_programs: Vec<Pubkey> = inner_instructions[0]
|
||||
.iter()
|
||||
.map(|ix| message.account_keys[ix.program_id_index as usize].clone())
|
||||
.collect();
|
||||
assert_eq!(invoked_programs, vec![]);
|
||||
assert_eq!(
|
||||
result.unwrap_err(),
|
||||
TransactionError::InstructionError(0, InstructionError::Custom(194969602))
|
||||
);
|
||||
|
||||
// Check final state
|
||||
|
||||
assert_eq!(43, bank.get_balance(&derived_key1));
|
||||
|
@ -986,6 +1015,8 @@ fn test_program_bpf_ro_modify() {
|
|||
#[cfg(feature = "bpf_rust")]
|
||||
#[test]
|
||||
fn test_program_bpf_call_depth() {
|
||||
use solana_sdk::process_instruction::BpfComputeBudget;
|
||||
|
||||
solana_logger::setup();
|
||||
|
||||
println!("Test program: solana_bpf_rust_call_depth");
|
||||
|
@ -1139,6 +1170,8 @@ fn test_program_bpf_instruction_introspection() {
|
|||
#[cfg(feature = "bpf_rust")]
|
||||
#[test]
|
||||
fn test_program_bpf_test_use_latest_executor() {
|
||||
use solana_sdk::{loader_instruction, system_instruction};
|
||||
|
||||
solana_logger::setup();
|
||||
|
||||
let GenesisConfigInfo {
|
||||
|
@ -1229,6 +1262,8 @@ fn test_program_bpf_test_use_latest_executor() {
|
|||
#[cfg(feature = "bpf_rust")]
|
||||
#[test]
|
||||
fn test_program_bpf_test_use_latest_executor2() {
|
||||
use solana_sdk::{loader_instruction, system_instruction};
|
||||
|
||||
solana_logger::setup();
|
||||
|
||||
let GenesisConfigInfo {
|
||||
|
|
|
@ -37,6 +37,9 @@ use std::{
|
|||
};
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
/// Maximum signers
|
||||
pub const MAX_SIGNERS: usize = 16;
|
||||
|
||||
/// Error definitions
|
||||
#[derive(Debug, ThisError, PartialEq)]
|
||||
pub enum SyscallError {
|
||||
|
@ -60,6 +63,8 @@ pub enum SyscallError {
|
|||
PrivilegeEscalation,
|
||||
#[error("Unaligned pointer")]
|
||||
UnalignedPointer,
|
||||
#[error("Too many signers")]
|
||||
TooManySigners,
|
||||
}
|
||||
impl From<SyscallError> for EbpfError<BPFError> {
|
||||
fn from(error: SyscallError) -> Self {
|
||||
|
@ -923,6 +928,9 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
|
|||
signers_seeds_len,
|
||||
self.loader_id,
|
||||
)?;
|
||||
if signers_seeds.len() > MAX_SIGNERS {
|
||||
return Err(SyscallError::TooManySigners.into());
|
||||
}
|
||||
for signer_seeds in signers_seeds.iter() {
|
||||
let untranslated_seeds = translate_slice::<&[u8]>(
|
||||
memory_mapping,
|
||||
|
@ -1178,6 +1186,9 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> {
|
|||
signers_seeds_len,
|
||||
self.loader_id,
|
||||
)?;
|
||||
if signers_seeds.len() > MAX_SIGNERS {
|
||||
return Err(SyscallError::TooManySigners.into());
|
||||
}
|
||||
Ok(signers_seeds
|
||||
.iter()
|
||||
.map(|signer_seeds| {
|
||||
|
|
Loading…
Reference in New Issue