Cap CPI signers (#14021)
This commit is contained in:
@ -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_PPROGRAM_NOT_EXECUTABLE = 4;
|
||||||
static const uint8_t TEST_EMPTY_ACCOUNTS_SLICE = 5;
|
static const uint8_t TEST_EMPTY_ACCOUNTS_SLICE = 5;
|
||||||
static const uint8_t TEST_CAP_SEEDS = 6;
|
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 MINT_INDEX = 0;
|
||||||
static const int ARGUMENT_INDEX = 1;
|
static const int ARGUMENT_INDEX = 1;
|
||||||
@ -285,7 +286,6 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
|||||||
}
|
}
|
||||||
case TEST_CAP_SEEDS: {
|
case TEST_CAP_SEEDS: {
|
||||||
sol_log("Test cap seeds");
|
sol_log("Test cap seeds");
|
||||||
{
|
|
||||||
SolAccountMeta arguments[] = {};
|
SolAccountMeta arguments[] = {};
|
||||||
uint8_t data[] = {};
|
uint8_t data[] = {};
|
||||||
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
|
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)},
|
{seed, SOL_ARRAY_SIZE(seed)},
|
||||||
};
|
};
|
||||||
const SolSignerSeeds signers_seeds[] = {{seeds, SOL_ARRAY_SIZE(seeds)}};
|
const SolSignerSeeds signers_seeds[] = {{seeds, SOL_ARRAY_SIZE(seeds)}};
|
||||||
sol_assert(SUCCESS == sol_invoke_signed(&instruction, accounts,
|
sol_assert(SUCCESS == sol_invoke_signed(
|
||||||
SOL_ARRAY_SIZE(accounts),
|
&instruction, accounts, SOL_ARRAY_SIZE(accounts),
|
||||||
signers_seeds,
|
signers_seeds, SOL_ARRAY_SIZE(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:
|
default:
|
||||||
sol_panic();
|
sol_panic();
|
||||||
|
@ -22,6 +22,7 @@ const TEST_PRIVILEGE_ESCALATION_WRITABLE: u8 = 3;
|
|||||||
const TEST_PPROGRAM_NOT_EXECUTABLE: u8 = 4;
|
const TEST_PPROGRAM_NOT_EXECUTABLE: u8 = 4;
|
||||||
const TEST_EMPTY_ACCOUNTS_SLICE: u8 = 5;
|
const TEST_EMPTY_ACCOUNTS_SLICE: u8 = 5;
|
||||||
const TEST_CAP_SEEDS: u8 = 6;
|
const TEST_CAP_SEEDS: u8 = 6;
|
||||||
|
const TEST_CAP_SIGNERS: u8 = 7;
|
||||||
|
|
||||||
// const MINT_INDEX: usize = 0;
|
// const MINT_INDEX: usize = 0;
|
||||||
const ARGUMENT_INDEX: usize = 1;
|
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!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,12 +24,10 @@ use solana_sdk::{
|
|||||||
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
||||||
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
|
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
|
||||||
keyed_account::KeyedAccount,
|
keyed_account::KeyedAccount,
|
||||||
loader_instruction,
|
|
||||||
message::Message,
|
message::Message,
|
||||||
process_instruction::{BpfComputeBudget, InvokeContext, MockInvokeContext},
|
process_instruction::{InvokeContext, MockInvokeContext},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
system_instruction,
|
|
||||||
sysvar::{clock, fees, rent, slot_hashes, stake_history},
|
sysvar::{clock, fees, rent, slot_hashes, stake_history},
|
||||||
transaction::{Transaction, TransactionError},
|
transaction::{Transaction, TransactionError},
|
||||||
};
|
};
|
||||||
@ -71,6 +69,7 @@ fn read_bpf_program(name: &str) -> Vec<u8> {
|
|||||||
elf
|
elf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bpf_rust")]
|
||||||
fn write_bpf_program(
|
fn write_bpf_program(
|
||||||
bank_client: &BankClient,
|
bank_client: &BankClient,
|
||||||
loader_id: &Pubkey,
|
loader_id: &Pubkey,
|
||||||
@ -78,6 +77,8 @@ fn write_bpf_program(
|
|||||||
program_keypair: &Keypair,
|
program_keypair: &Keypair,
|
||||||
elf: &[u8],
|
elf: &[u8],
|
||||||
) {
|
) {
|
||||||
|
use solana_sdk::loader_instruction;
|
||||||
|
|
||||||
let chunk_size = 256; // Size of chunk just needs to fit into tx
|
let chunk_size = 256; // Size of chunk just needs to fit into tx
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for chunk in elf.chunks(chunk_size) {
|
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_PPROGRAM_NOT_EXECUTABLE: u8 = 4;
|
||||||
const TEST_EMPTY_ACCOUNTS_SLICE: u8 = 5;
|
const TEST_EMPTY_ACCOUNTS_SLICE: u8 = 5;
|
||||||
const TEST_CAP_SEEDS: u8 = 6;
|
const TEST_CAP_SEEDS: u8 = 6;
|
||||||
|
const TEST_CAP_SIGNERS: u8 = 7;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -823,6 +825,33 @@ fn test_program_bpf_invoke() {
|
|||||||
TransactionError::InstructionError(0, InstructionError::MaxSeedLengthExceeded)
|
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
|
// Check final state
|
||||||
|
|
||||||
assert_eq!(43, bank.get_balance(&derived_key1));
|
assert_eq!(43, bank.get_balance(&derived_key1));
|
||||||
@ -986,6 +1015,8 @@ fn test_program_bpf_ro_modify() {
|
|||||||
#[cfg(feature = "bpf_rust")]
|
#[cfg(feature = "bpf_rust")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_program_bpf_call_depth() {
|
fn test_program_bpf_call_depth() {
|
||||||
|
use solana_sdk::process_instruction::BpfComputeBudget;
|
||||||
|
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
|
||||||
println!("Test program: solana_bpf_rust_call_depth");
|
println!("Test program: solana_bpf_rust_call_depth");
|
||||||
@ -1139,6 +1170,8 @@ fn test_program_bpf_instruction_introspection() {
|
|||||||
#[cfg(feature = "bpf_rust")]
|
#[cfg(feature = "bpf_rust")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_program_bpf_test_use_latest_executor() {
|
fn test_program_bpf_test_use_latest_executor() {
|
||||||
|
use solana_sdk::{loader_instruction, system_instruction};
|
||||||
|
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
|
||||||
let GenesisConfigInfo {
|
let GenesisConfigInfo {
|
||||||
@ -1229,6 +1262,8 @@ fn test_program_bpf_test_use_latest_executor() {
|
|||||||
#[cfg(feature = "bpf_rust")]
|
#[cfg(feature = "bpf_rust")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_program_bpf_test_use_latest_executor2() {
|
fn test_program_bpf_test_use_latest_executor2() {
|
||||||
|
use solana_sdk::{loader_instruction, system_instruction};
|
||||||
|
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
|
||||||
let GenesisConfigInfo {
|
let GenesisConfigInfo {
|
||||||
|
@ -37,6 +37,9 @@ use std::{
|
|||||||
};
|
};
|
||||||
use thiserror::Error as ThisError;
|
use thiserror::Error as ThisError;
|
||||||
|
|
||||||
|
/// Maximum signers
|
||||||
|
pub const MAX_SIGNERS: usize = 16;
|
||||||
|
|
||||||
/// Error definitions
|
/// Error definitions
|
||||||
#[derive(Debug, ThisError, PartialEq)]
|
#[derive(Debug, ThisError, PartialEq)]
|
||||||
pub enum SyscallError {
|
pub enum SyscallError {
|
||||||
@ -60,6 +63,8 @@ pub enum SyscallError {
|
|||||||
PrivilegeEscalation,
|
PrivilegeEscalation,
|
||||||
#[error("Unaligned pointer")]
|
#[error("Unaligned pointer")]
|
||||||
UnalignedPointer,
|
UnalignedPointer,
|
||||||
|
#[error("Too many signers")]
|
||||||
|
TooManySigners,
|
||||||
}
|
}
|
||||||
impl From<SyscallError> for EbpfError<BPFError> {
|
impl From<SyscallError> for EbpfError<BPFError> {
|
||||||
fn from(error: SyscallError) -> Self {
|
fn from(error: SyscallError) -> Self {
|
||||||
@ -923,6 +928,9 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
|
|||||||
signers_seeds_len,
|
signers_seeds_len,
|
||||||
self.loader_id,
|
self.loader_id,
|
||||||
)?;
|
)?;
|
||||||
|
if signers_seeds.len() > MAX_SIGNERS {
|
||||||
|
return Err(SyscallError::TooManySigners.into());
|
||||||
|
}
|
||||||
for signer_seeds in signers_seeds.iter() {
|
for signer_seeds in signers_seeds.iter() {
|
||||||
let untranslated_seeds = translate_slice::<&[u8]>(
|
let untranslated_seeds = translate_slice::<&[u8]>(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
@ -1178,6 +1186,9 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> {
|
|||||||
signers_seeds_len,
|
signers_seeds_len,
|
||||||
self.loader_id,
|
self.loader_id,
|
||||||
)?;
|
)?;
|
||||||
|
if signers_seeds.len() > MAX_SIGNERS {
|
||||||
|
return Err(SyscallError::TooManySigners.into());
|
||||||
|
}
|
||||||
Ok(signers_seeds
|
Ok(signers_seeds
|
||||||
.iter()
|
.iter()
|
||||||
.map(|signer_seeds| {
|
.map(|signer_seeds| {
|
||||||
|
Reference in New Issue
Block a user