Remove native id check in pda creation (backport #19595) (#19689)

* Remove native id check in pda creation (#19595)

(cherry picked from commit 529fefc7cc)

# Conflicts:
#	programs/bpf/rust/invoke/src/lib.rs
#	programs/bpf_loader/src/syscalls.rs
#	sdk/src/feature_set.rs

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
This commit is contained in:
mergify[bot]
2021-09-07 23:26:08 -07:00
committed by GitHub
parent 57e87a09c0
commit e9c3f11d24
4 changed files with 85 additions and 89 deletions

View File

@ -263,10 +263,9 @@ fn process_instruction(
)?, )?,
accounts[DERIVED_KEY1_INDEX].key accounts[DERIVED_KEY1_INDEX].key
); );
let not_native_program_id = Pubkey::new_from_array([6u8; 32]); let new_program_id = Pubkey::new_from_array([6u8; 32]);
assert!(!not_native_program_id.is_native_program_id());
assert_eq!( assert_eq!(
Pubkey::create_program_address(&[b"You pass butter"], &not_native_program_id) Pubkey::create_program_address(&[b"You pass butter"], &new_program_id)
.unwrap_err(), .unwrap_err(),
PubkeyError::InvalidSeeds PubkeyError::InvalidSeeds
); );
@ -278,10 +277,9 @@ fn process_instruction(
Pubkey::try_find_program_address(&[b"You pass butter"], program_id).unwrap(); Pubkey::try_find_program_address(&[b"You pass butter"], program_id).unwrap();
assert_eq!(&address, accounts[DERIVED_KEY1_INDEX].key); assert_eq!(&address, accounts[DERIVED_KEY1_INDEX].key);
assert_eq!(bump_seed, bump_seed1); assert_eq!(bump_seed, bump_seed1);
let not_native_program_id = Pubkey::new_from_array([6u8; 32]); let new_program_id = Pubkey::new_from_array([6u8; 32]);
assert!(!not_native_program_id.is_native_program_id());
assert_eq!( assert_eq!(
Pubkey::create_program_address(&[b"You pass butter"], &not_native_program_id) Pubkey::create_program_address(&[b"You pass butter"], &new_program_id)
.unwrap_err(), .unwrap_err(),
PubkeyError::InvalidSeeds PubkeyError::InvalidSeeds
); );
@ -653,16 +651,3 @@ fn process_instruction(
Ok(()) Ok(())
} }
#[cfg(test)]
mod test {
use super::*;
#[test]
fn create_program_address_is_defined() {
assert_eq!(
Pubkey::create_program_address(&[b"You pass butter"], &Pubkey::default()).unwrap_err(),
PubkeyError::InvalidSeeds
);
}
}

View File

@ -19,10 +19,11 @@ use solana_sdk::{
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS}, entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
epoch_schedule::EpochSchedule, epoch_schedule::EpochSchedule,
feature_set::{ feature_set::{
close_upgradeable_program_accounts, cpi_data_cost, demote_program_write_locks, allow_native_ids, close_upgradeable_program_accounts, cpi_data_cost,
enforce_aligned_host_addrs, keccak256_syscall_enabled, libsecp256k1_0_5_upgrade_enabled, demote_program_write_locks, enforce_aligned_host_addrs, keccak256_syscall_enabled,
mem_overlap_fix, memory_ops_syscalls, secp256k1_recover_syscall_enabled, libsecp256k1_0_5_upgrade_enabled, mem_overlap_fix, memory_ops_syscalls,
set_upgrade_authority_via_cpi_enabled, sysvar_via_syscall, update_data_on_realloc, secp256k1_recover_syscall_enabled, set_upgrade_authority_via_cpi_enabled,
sysvar_via_syscall, update_data_on_realloc,
}, },
hash::{Hasher, HASH_BYTES}, hash::{Hasher, HASH_BYTES},
ic_msg, ic_msg,
@ -31,7 +32,7 @@ use solana_sdk::{
keyed_account::KeyedAccount, keyed_account::KeyedAccount,
native_loader, native_loader,
process_instruction::{self, stable_log, ComputeMeter, InvokeContext, Logger}, process_instruction::{self, stable_log, ComputeMeter, InvokeContext, Logger},
pubkey::{Pubkey, PubkeyError, MAX_SEEDS}, pubkey::{Pubkey, PubkeyError, MAX_SEEDS, MAX_SEED_LEN},
rent::Rent, rent::Rent,
secp256k1_recover::{ secp256k1_recover::{
Secp256k1RecoverError, SECP256K1_PUBLIC_KEY_LENGTH, SECP256K1_SIGNATURE_LENGTH, Secp256k1RecoverError, SECP256K1_PUBLIC_KEY_LENGTH, SECP256K1_SIGNATURE_LENGTH,
@ -247,22 +248,24 @@ pub fn bind_syscall_context_objects<'a>(
None, None,
)?; )?;
let allow_native_ids = invoke_context.is_feature_active(&allow_native_ids::id());
vm.bind_syscall_context_object( vm.bind_syscall_context_object(
Box::new(SyscallCreateProgramAddress { Box::new(SyscallCreateProgramAddress {
cost: bpf_compute_budget.create_program_address_units, cost: bpf_compute_budget.create_program_address_units,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
enforce_aligned_host_addrs, enforce_aligned_host_addrs,
allow_native_ids,
}), }),
None, None,
)?; )?;
vm.bind_syscall_context_object( vm.bind_syscall_context_object(
Box::new(SyscallTryFindProgramAddress { Box::new(SyscallTryFindProgramAddress {
cost: bpf_compute_budget.create_program_address_units, cost: bpf_compute_budget.create_program_address_units,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
enforce_aligned_host_addrs, enforce_aligned_host_addrs,
allow_native_ids,
}), }),
None, None,
)?; )?;
@ -830,12 +833,42 @@ fn translate_program_address_inputs<'a>(
Ok((seeds, program_id)) Ok((seeds, program_id))
} }
fn is_native_id(seeds: &[&[u8]], program_id: &Pubkey) -> bool {
use solana_sdk::{config, feature, secp256k1_program, stake, system_program, vote};
// Does more than just check native ids in order to emulate the same failure
// signature that `compute_program_address` had before the removal of the
// check.
if seeds.len() > MAX_SEEDS {
return true;
}
for seed in seeds.iter() {
if seed.len() > MAX_SEED_LEN {
return true;
}
}
let native_ids = [
bpf_loader::id(),
bpf_loader_deprecated::id(),
feature::id(),
config::program::id(),
stake::program::id(),
stake::config::id(),
vote::program::id(),
secp256k1_program::id(),
system_program::id(),
sysvar::id(),
];
native_ids.contains(program_id)
}
/// Create a program address /// Create a program address
struct SyscallCreateProgramAddress<'a> { struct SyscallCreateProgramAddress<'a> {
cost: u64, cost: u64,
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
loader_id: &'a Pubkey, loader_id: &'a Pubkey,
enforce_aligned_host_addrs: bool, enforce_aligned_host_addrs: bool,
allow_native_ids: bool,
} }
impl<'a> SyscallObject<BpfError> for SyscallCreateProgramAddress<'a> { impl<'a> SyscallObject<BpfError> for SyscallCreateProgramAddress<'a> {
fn call( fn call(
@ -861,6 +894,12 @@ impl<'a> SyscallObject<BpfError> for SyscallCreateProgramAddress<'a> {
); );
question_mark!(self.compute_meter.consume(self.cost), result); question_mark!(self.compute_meter.consume(self.cost), result);
if !self.allow_native_ids && is_native_id(&seeds, program_id) {
*result = Ok(1);
return;
}
let new_address = match Pubkey::create_program_address(&seeds, program_id) { let new_address = match Pubkey::create_program_address(&seeds, program_id) {
Ok(address) => address, Ok(address) => address,
Err(_) => { Err(_) => {
@ -889,6 +928,7 @@ struct SyscallTryFindProgramAddress<'a> {
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
loader_id: &'a Pubkey, loader_id: &'a Pubkey,
enforce_aligned_host_addrs: bool, enforce_aligned_host_addrs: bool,
allow_native_ids: bool,
} }
impl<'a> SyscallObject<BpfError> for SyscallTryFindProgramAddress<'a> { impl<'a> SyscallObject<BpfError> for SyscallTryFindProgramAddress<'a> {
fn call( fn call(
@ -920,32 +960,35 @@ impl<'a> SyscallObject<BpfError> for SyscallTryFindProgramAddress<'a> {
seeds_with_bump.push(&bump_seed); seeds_with_bump.push(&bump_seed);
question_mark!(self.compute_meter.consume(self.cost), result); question_mark!(self.compute_meter.consume(self.cost), result);
if let Ok(new_address) =
Pubkey::create_program_address(&seeds_with_bump, program_id) if self.allow_native_ids || !is_native_id(&seeds, program_id) {
{ if let Ok(new_address) =
let bump_seed_ref = question_mark!( Pubkey::create_program_address(&seeds_with_bump, program_id)
translate_type_mut::<u8>( {
memory_mapping, let bump_seed_ref = question_mark!(
bump_seed_addr, translate_type_mut::<u8>(
self.loader_id, memory_mapping,
self.enforce_aligned_host_addrs, bump_seed_addr,
), self.loader_id,
result self.enforce_aligned_host_addrs,
); ),
let address = question_mark!( result
translate_slice_mut::<u8>( );
memory_mapping, let address = question_mark!(
address_addr, translate_slice_mut::<u8>(
32, memory_mapping,
self.loader_id, address_addr,
self.enforce_aligned_host_addrs, 32,
), self.loader_id,
result self.enforce_aligned_host_addrs,
); ),
*bump_seed_ref = bump_seed[0]; result
address.copy_from_slice(new_address.as_ref()); );
*result = Ok(0); *bump_seed_ref = bump_seed[0];
return; address.copy_from_slice(new_address.as_ref());
*result = Ok(0);
return;
}
} }
} }
bump_seed[0] -= 1; bump_seed[0] -= 1;

View File

@ -1,8 +1,5 @@
#![allow(clippy::integer_arithmetic)] #![allow(clippy::integer_arithmetic)]
use crate::{ use crate::{decode_error::DecodeError, hash::hashv};
bpf_loader, bpf_loader_deprecated, config, decode_error::DecodeError, feature, hash::hashv,
secp256k1_program, stake, system_program, sysvar, vote,
};
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
@ -214,10 +211,6 @@ impl Pubkey {
} }
} }
if program_id.is_native_program_id() {
return Err(PubkeyError::IllegalOwner);
}
// Perform the calculation inline, calling this from within a program is // Perform the calculation inline, calling this from within a program is
// not supported // not supported
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
@ -368,22 +361,6 @@ impl Pubkey {
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
crate::program_stubs::sol_log(&self.to_string()); crate::program_stubs::sol_log(&self.to_string());
} }
pub fn is_native_program_id(&self) -> bool {
let all_program_ids = [
bpf_loader::id(),
bpf_loader_deprecated::id(),
feature::id(),
config::program::id(),
stake::program::id(),
stake::config::id(),
vote::program::id(),
secp256k1_program::id(),
system_program::id(),
sysvar::id(),
];
all_program_ids.contains(self)
}
} }
impl AsRef<[u8]> for Pubkey { impl AsRef<[u8]> for Pubkey {
@ -600,20 +577,6 @@ mod tests {
} }
} }
#[test]
fn test_is_native_program_id() {
assert!(bpf_loader::id().is_native_program_id());
assert!(bpf_loader_deprecated::id().is_native_program_id());
assert!(config::program::id().is_native_program_id());
assert!(feature::id().is_native_program_id());
assert!(secp256k1_program::id().is_native_program_id());
assert!(stake::program::id().is_native_program_id());
assert!(stake::config::id().is_native_program_id());
assert!(system_program::id().is_native_program_id());
assert!(sysvar::id().is_native_program_id());
assert!(vote::program::id().is_native_program_id());
}
fn pubkey_from_seed_by_marker(marker: &[u8]) -> Result<Pubkey, PubkeyError> { fn pubkey_from_seed_by_marker(marker: &[u8]) -> Result<Pubkey, PubkeyError> {
let key = Pubkey::new_unique(); let key = Pubkey::new_unique();
let owner = Pubkey::default(); let owner = Pubkey::default();

View File

@ -191,6 +191,10 @@ pub mod demote_program_write_locks {
solana_sdk::declare_id!("3E3jV7v9VcdJL8iYZUMax9DiDno8j7EWUVbhm9RtShj2"); solana_sdk::declare_id!("3E3jV7v9VcdJL8iYZUMax9DiDno8j7EWUVbhm9RtShj2");
} }
pub mod allow_native_ids {
solana_sdk::declare_id!("GVnDbNkECwrzLM7aVBGWpBYo3yH1ACaXB4ottNX8pedZ");
}
lazy_static! { lazy_static! {
/// Map of feature identifiers to user-visible description /// Map of feature identifiers to user-visible description
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [ pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
@ -239,6 +243,7 @@ lazy_static! {
(close_upgradeable_program_accounts::id(), "enable closing upgradeable program accounts"), (close_upgradeable_program_accounts::id(), "enable closing upgradeable program accounts"),
(stake_program_advance_activating_credits_observed::id(), "Enable advancing credits observed for activation epoch #19309"), (stake_program_advance_activating_credits_observed::id(), "Enable advancing credits observed for activation epoch #19309"),
(demote_program_write_locks::id(), "demote program write locks to readonly #19593"), (demote_program_write_locks::id(), "demote program write locks to readonly #19593"),
(allow_native_ids::id(), "allow native program ids in program derived addresses"),
/*************** ADD NEW FEATURES HERE ***************/ /*************** ADD NEW FEATURES HERE ***************/
] ]
.iter() .iter()