1#![cfg(feature = "agave-unstable-api")]
2#![deny(clippy::arithmetic_side_effects)]
3#![deny(clippy::indexing_slicing)]
4
5#[cfg(feature = "svm-internal")]
6use qualifier_attr::qualifiers;
7use {
8 solana_bincode::limited_deserialize,
9 solana_instruction::{AccountMeta, error::InstructionError},
10 solana_loader_v3_interface::{
11 instruction::{MINIMUM_EXTEND_PROGRAM_BYTES, UpgradeableLoaderInstruction},
12 state::UpgradeableLoaderState,
13 },
14 solana_program_runtime::{
15 deploy_program,
16 invoke_context::InvokeContext,
17 program_cache_entry::{ProgramCacheEntry, ProgramCacheEntryOwner, ProgramCacheEntryType},
18 sysvar_cache::get_sysvar_with_account_check,
19 vm::execute,
20 },
21 solana_pubkey::Pubkey,
22 solana_sbpf::{declare_builtin_function, elf::get_sbpf_version, program::SBPFVersion},
23 solana_sdk_ids::{bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, native_loader},
24 solana_svm_log_collector::{LogCollector, ic_logger_msg, ic_msg},
25 solana_svm_measure::measure::Measure,
26 solana_svm_type_overrides::sync::Arc,
27 solana_system_interface::{MAX_PERMITTED_DATA_LENGTH, instruction as system_instruction},
28 solana_transaction_context::{IndexOfAccount, instruction::InstructionContext},
29 std::{cell::RefCell, rc::Rc},
30};
31
32#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
33const DEFAULT_LOADER_COMPUTE_UNITS: u64 = 570;
34#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
35const DEPRECATED_LOADER_COMPUTE_UNITS: u64 = 1_140;
36#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
37const UPGRADEABLE_LOADER_COMPUTE_UNITS: u64 = 2_370;
38
39fn write_program_data(
40 program_data_offset: usize,
41 bytes: &[u8],
42 invoke_context: &mut InvokeContext,
43) -> Result<(), InstructionError> {
44 let transaction_context = &invoke_context.transaction_context;
45 let instruction_context = transaction_context.get_current_instruction_context()?;
46 let mut program = instruction_context.try_borrow_instruction_account(0)?;
47 let data = program.get_data_mut()?;
48 let write_offset = program_data_offset.saturating_add(bytes.len());
49 if data.len() < write_offset {
50 ic_msg!(
51 invoke_context,
52 "Write overflow: {} < {}",
53 data.len(),
54 write_offset,
55 );
56 return Err(InstructionError::AccountDataTooSmall);
57 }
58 data.get_mut(program_data_offset..write_offset)
59 .ok_or(InstructionError::AccountDataTooSmall)?
60 .copy_from_slice(bytes);
61 Ok(())
62}
63
64declare_builtin_function!(
65 Entrypoint,
66 fn rust(
67 invoke_context: &mut InvokeContext<'static, 'static>,
68 _arg0: u64,
69 _arg1: u64,
70 _arg2: u64,
71 _arg3: u64,
72 _arg4: u64,
73 ) -> Result<u64, Box<dyn std::error::Error>> {
74 process_instruction_inner(invoke_context)
75 }
76);
77
78mod migration_authority {
79 solana_pubkey::declare_id!("3Scf35jMNk2xXBD6areNjgMtXgp5ZspDhms8vdcbzC42");
80}
81
82#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
83pub(crate) fn process_instruction_inner<'a>(
84 invoke_context: &mut InvokeContext<'a, 'a>,
85) -> Result<u64, Box<dyn std::error::Error>> {
86 let log_collector = invoke_context.get_log_collector();
87 let transaction_context = &invoke_context.transaction_context;
88 let instruction_context = transaction_context.get_current_instruction_context()?;
89 let program_id = instruction_context.get_program_key()?;
90 let owner_id = instruction_context.get_program_owner()?;
91
92 if native_loader::check_id(&owner_id) {
94 let program_id = instruction_context.get_program_key()?;
95 return if bpf_loader_upgradeable::check_id(program_id) {
96 invoke_context
97 .compute_meter
98 .consume_checked(UPGRADEABLE_LOADER_COMPUTE_UNITS)?;
99 process_loader_upgradeable_instruction(invoke_context)
100 } else if bpf_loader::check_id(program_id) {
101 invoke_context
102 .compute_meter
103 .consume_checked(DEFAULT_LOADER_COMPUTE_UNITS)?;
104 ic_logger_msg!(
105 log_collector,
106 "BPF loader management instructions are no longer supported",
107 );
108 Err(InstructionError::UnsupportedProgramId)
109 } else if bpf_loader_deprecated::check_id(program_id) {
110 invoke_context
111 .compute_meter
112 .consume_checked(DEPRECATED_LOADER_COMPUTE_UNITS)?;
113 ic_logger_msg!(log_collector, "Deprecated loader is no longer supported");
114 Err(InstructionError::UnsupportedProgramId)
115 } else {
116 ic_logger_msg!(log_collector, "Invalid BPF loader id");
117 Err(InstructionError::UnsupportedProgramId)
118 }
119 .map(|_| 0)
120 .map_err(|error| Box::new(error) as Box<dyn std::error::Error>);
121 }
122
123 let mut get_or_create_executor_time = Measure::start("get_or_create_executor_time");
125 let executor = invoke_context
126 .program_cache_for_tx_batch
127 .find(program_id)
128 .ok_or_else(|| {
129 ic_logger_msg!(log_collector, "Program is not cached");
130 InstructionError::UnsupportedProgramId
131 })?;
132 get_or_create_executor_time.stop();
133 invoke_context.timings.get_or_create_executor_us += get_or_create_executor_time.as_us();
134
135 match &executor.program {
136 ProgramCacheEntryType::FailedVerification(_)
137 | ProgramCacheEntryType::Closed
138 | ProgramCacheEntryType::DelayVisibility => {
139 ic_logger_msg!(log_collector, "Program is not deployed");
140 Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>)
141 }
142 ProgramCacheEntryType::Loaded(executable) => execute(executable, invoke_context, &executor),
143 _ => Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>),
144 }
145 .map(|_| 0)
146}
147
148fn process_loader_upgradeable_instruction(
149 invoke_context: &mut InvokeContext,
150) -> Result<(), InstructionError> {
151 let log_collector = invoke_context.get_log_collector();
152 let transaction_context = &invoke_context.transaction_context;
153 let instruction_context = transaction_context.get_current_instruction_context()?;
154 let instruction_data = instruction_context.get_instruction_data();
155 let program_id = instruction_context.get_program_key()?;
156
157 match limited_deserialize(instruction_data, solana_packet::PACKET_DATA_SIZE as u64)? {
158 UpgradeableLoaderInstruction::InitializeBuffer => {
159 instruction_context.check_number_of_instruction_accounts(2)?;
160 let mut buffer = instruction_context.try_borrow_instruction_account(0)?;
161
162 if UpgradeableLoaderState::Uninitialized != buffer.get_state()? {
163 ic_logger_msg!(log_collector, "Buffer account already initialized");
164 return Err(InstructionError::AccountAlreadyInitialized);
165 }
166
167 let authority_key = Some(*instruction_context.get_key_of_instruction_account(1)?);
168
169 buffer.set_state(&UpgradeableLoaderState::Buffer {
170 authority_address: authority_key,
171 })?;
172 }
173 UpgradeableLoaderInstruction::Write { offset, bytes } => {
174 instruction_context.check_number_of_instruction_accounts(2)?;
175 let buffer = instruction_context.try_borrow_instruction_account(0)?;
176
177 if let UpgradeableLoaderState::Buffer { authority_address } = buffer.get_state()? {
178 if authority_address.is_none() {
179 ic_logger_msg!(log_collector, "Buffer is immutable");
180 return Err(InstructionError::Immutable); }
182 let authority_key = Some(*instruction_context.get_key_of_instruction_account(1)?);
183 if authority_address != authority_key {
184 ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
185 return Err(InstructionError::IncorrectAuthority);
186 }
187 if !instruction_context.is_instruction_account_signer(1)? {
188 ic_logger_msg!(log_collector, "Buffer authority did not sign");
189 return Err(InstructionError::MissingRequiredSignature);
190 }
191 } else {
192 ic_logger_msg!(log_collector, "Invalid Buffer account");
193 return Err(InstructionError::InvalidAccountData);
194 }
195 drop(buffer);
196 write_program_data(
197 UpgradeableLoaderState::size_of_buffer_metadata().saturating_add(offset as usize),
198 &bytes,
199 invoke_context,
200 )?;
201 }
202 UpgradeableLoaderInstruction::DeployWithMaxDataLen { max_data_len } => {
203 instruction_context.check_number_of_instruction_accounts(4)?;
204 let payer_key = *instruction_context.get_key_of_instruction_account(0)?;
205 let programdata_key = *instruction_context.get_key_of_instruction_account(1)?;
206 let rent =
207 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 4)?;
208 let clock =
209 get_sysvar_with_account_check::clock(invoke_context, &instruction_context, 5)?;
210 instruction_context.check_number_of_instruction_accounts(8)?;
211 let authority_key = Some(*instruction_context.get_key_of_instruction_account(7)?);
212
213 let program = instruction_context.try_borrow_instruction_account(2)?;
216 if UpgradeableLoaderState::Uninitialized != program.get_state()? {
217 ic_logger_msg!(log_collector, "Program account already initialized");
218 return Err(InstructionError::AccountAlreadyInitialized);
219 }
220 if program.get_data().len() < UpgradeableLoaderState::size_of_program() {
221 ic_logger_msg!(log_collector, "Program account too small");
222 return Err(InstructionError::AccountDataTooSmall);
223 }
224 if program.get_lamports() < rent.minimum_balance(program.get_data().len()) {
225 ic_logger_msg!(log_collector, "Program account not rent-exempt");
226 return Err(InstructionError::ExecutableAccountNotRentExempt);
227 }
228 let new_program_id = *program.get_key();
229 drop(program);
230
231 let buffer = instruction_context.try_borrow_instruction_account(3)?;
234 if !buffer.is_writable() {
235 ic_logger_msg!(log_collector, "Buffer account not writeable");
236 return Err(InstructionError::InvalidArgument);
237 }
238 if buffer.get_owner() != program_id {
239 ic_logger_msg!(log_collector, "Buffer account not owned by loader");
240 return Err(InstructionError::IncorrectProgramId);
241 }
242 if let UpgradeableLoaderState::Buffer { authority_address } = buffer.get_state()? {
243 if authority_address != authority_key {
244 ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
245 return Err(InstructionError::IncorrectAuthority);
246 }
247 if !instruction_context.is_instruction_account_signer(7)? {
248 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
249 return Err(InstructionError::MissingRequiredSignature);
250 }
251 } else {
252 ic_logger_msg!(log_collector, "Invalid Buffer account");
253 return Err(InstructionError::InvalidArgument);
254 }
255 let buffer_key = *buffer.get_key();
256 let buffer_data_offset = UpgradeableLoaderState::size_of_buffer_metadata();
257 let buffer_data_len = buffer.get_data().len().saturating_sub(buffer_data_offset);
258 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
259 let programdata_len = UpgradeableLoaderState::size_of_programdata(max_data_len);
260 if buffer.get_data().len() < UpgradeableLoaderState::size_of_buffer_metadata()
261 || buffer_data_len == 0
262 {
263 ic_logger_msg!(log_collector, "Buffer account too small");
264 return Err(InstructionError::InvalidAccountData);
265 }
266 drop(buffer);
267 if max_data_len < buffer_data_len {
268 ic_logger_msg!(
269 log_collector,
270 "Max data length is too small to hold Buffer data"
271 );
272 return Err(InstructionError::AccountDataTooSmall);
273 }
274 if programdata_len > MAX_PERMITTED_DATA_LENGTH as usize {
275 ic_logger_msg!(log_collector, "Max data length is too large");
276 return Err(InstructionError::InvalidArgument);
277 }
278
279 let (derived_address, bump_seed) =
281 Pubkey::find_program_address(&[new_program_id.as_ref()], program_id);
282 if derived_address != programdata_key {
283 ic_logger_msg!(log_collector, "ProgramData address is not derived");
284 return Err(InstructionError::InvalidArgument);
285 }
286
287 {
289 let mut buffer = instruction_context.try_borrow_instruction_account(3)?;
290 let mut payer = instruction_context.try_borrow_instruction_account(0)?;
291 payer.checked_add_lamports(buffer.get_lamports())?;
292 buffer.set_lamports(0)?;
293 }
294
295 let owner_id = *program_id;
296 let mut instruction = system_instruction::create_account(
297 &payer_key,
298 &programdata_key,
299 1.max(rent.minimum_balance(programdata_len)),
300 programdata_len as u64,
301 program_id,
302 );
303
304 instruction
306 .accounts
307 .push(AccountMeta::new(buffer_key, false));
308
309 invoke_context
310 .native_invoke_signed(instruction, &[&[new_program_id.as_ref(), &[bump_seed]]])?;
311
312 let transaction_context = &invoke_context.transaction_context;
314 let instruction_context = transaction_context.get_current_instruction_context()?;
315 let buffer = instruction_context.try_borrow_instruction_account(3)?;
316 deploy_program!(
317 invoke_context,
318 &new_program_id,
319 &owner_id,
320 buffer
321 .get_data()
322 .get(buffer_data_offset..)
323 .ok_or(InstructionError::AccountDataTooSmall)?,
324 clock.slot,
325 invoke_context
326 .get_feature_set()
327 .disable_sbpf_v0_v1_v2_deployment,
328 );
329 drop(buffer);
330
331 let transaction_context = &invoke_context.transaction_context;
332 let instruction_context = transaction_context.get_current_instruction_context()?;
333
334 {
336 let mut programdata = instruction_context.try_borrow_instruction_account(1)?;
337 programdata.set_state(&UpgradeableLoaderState::ProgramData {
338 slot: clock.slot,
339 upgrade_authority_address: authority_key,
340 })?;
341 let dst_slice = programdata
342 .get_data_mut()?
343 .get_mut(
344 programdata_data_offset
345 ..programdata_data_offset.saturating_add(buffer_data_len),
346 )
347 .ok_or(InstructionError::AccountDataTooSmall)?;
348 let mut buffer = instruction_context.try_borrow_instruction_account(3)?;
349 let src_slice = buffer
350 .get_data()
351 .get(buffer_data_offset..)
352 .ok_or(InstructionError::AccountDataTooSmall)?;
353 dst_slice.copy_from_slice(src_slice);
354 buffer.set_data_length(UpgradeableLoaderState::size_of_buffer(0))?;
355 }
356
357 let mut program = instruction_context.try_borrow_instruction_account(2)?;
359 program.set_state(&UpgradeableLoaderState::Program {
360 programdata_address: programdata_key,
361 })?;
362 program.set_executable(true)?;
363 drop(program);
364
365 ic_logger_msg!(log_collector, "Deployed program {:?}", new_program_id);
366 }
367 UpgradeableLoaderInstruction::Upgrade => {
368 instruction_context.check_number_of_instruction_accounts(3)?;
369 let programdata_key = *instruction_context.get_key_of_instruction_account(0)?;
370 let rent =
371 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 4)?;
372 let clock =
373 get_sysvar_with_account_check::clock(invoke_context, &instruction_context, 5)?;
374 instruction_context.check_number_of_instruction_accounts(7)?;
375 let authority_key = Some(*instruction_context.get_key_of_instruction_account(6)?);
376
377 let program = instruction_context.try_borrow_instruction_account(1)?;
380 if !program.is_writable() {
381 ic_logger_msg!(log_collector, "Program account not writeable");
382 return Err(InstructionError::InvalidArgument);
383 }
384 if program.get_owner() != program_id {
385 ic_logger_msg!(log_collector, "Program account not owned by loader");
386 return Err(InstructionError::IncorrectProgramId);
387 }
388 if let UpgradeableLoaderState::Program {
389 programdata_address,
390 } = program.get_state()?
391 {
392 if programdata_address != programdata_key {
393 ic_logger_msg!(log_collector, "Program and ProgramData account mismatch");
394 return Err(InstructionError::InvalidArgument);
395 }
396 } else {
397 ic_logger_msg!(log_collector, "Invalid Program account");
398 return Err(InstructionError::InvalidAccountData);
399 }
400 let new_program_id = *program.get_key();
401 drop(program);
402
403 let buffer = instruction_context.try_borrow_instruction_account(2)?;
406 if !buffer.is_writable() {
407 ic_logger_msg!(log_collector, "Buffer account not writeable");
408 return Err(InstructionError::InvalidArgument);
409 }
410 if buffer.get_owner() != program_id {
411 ic_logger_msg!(log_collector, "Buffer account not owned by loader");
412 return Err(InstructionError::IncorrectProgramId);
413 }
414 if let UpgradeableLoaderState::Buffer { authority_address } = buffer.get_state()? {
415 if authority_address != authority_key {
416 ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
417 return Err(InstructionError::IncorrectAuthority);
418 }
419 if !instruction_context.is_instruction_account_signer(6)? {
420 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
421 return Err(InstructionError::MissingRequiredSignature);
422 }
423 } else {
424 ic_logger_msg!(log_collector, "Invalid Buffer account");
425 return Err(InstructionError::InvalidArgument);
426 }
427 let buffer_lamports = buffer.get_lamports();
428 let buffer_data_offset = UpgradeableLoaderState::size_of_buffer_metadata();
429 let buffer_data_len = buffer.get_data().len().saturating_sub(buffer_data_offset);
430 if buffer.get_data().len() < UpgradeableLoaderState::size_of_buffer_metadata()
431 || buffer_data_len == 0
432 {
433 ic_logger_msg!(log_collector, "Buffer account too small");
434 return Err(InstructionError::InvalidAccountData);
435 }
436 drop(buffer);
437
438 let programdata = instruction_context.try_borrow_instruction_account(0)?;
441 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
442 let programdata_balance_required =
443 1.max(rent.minimum_balance(programdata.get_data().len()));
444 if programdata.get_data().len()
445 < UpgradeableLoaderState::size_of_programdata(buffer_data_len)
446 {
447 ic_logger_msg!(log_collector, "ProgramData account not large enough");
448 return Err(InstructionError::AccountDataTooSmall);
449 }
450 if programdata.get_lamports().saturating_add(buffer_lamports)
451 < programdata_balance_required
452 {
453 ic_logger_msg!(
454 log_collector,
455 "Buffer account balance too low to fund upgrade"
456 );
457 return Err(InstructionError::InsufficientFunds);
458 }
459 if let UpgradeableLoaderState::ProgramData {
460 slot,
461 upgrade_authority_address,
462 } = programdata.get_state()?
463 {
464 if clock.slot == slot {
465 ic_logger_msg!(log_collector, "Program was deployed in this block already");
466 return Err(InstructionError::InvalidArgument);
467 }
468 if upgrade_authority_address.is_none() {
469 ic_logger_msg!(log_collector, "Program not upgradeable");
470 return Err(InstructionError::Immutable);
471 }
472 if upgrade_authority_address != authority_key {
473 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
474 return Err(InstructionError::IncorrectAuthority);
475 }
476 if !instruction_context.is_instruction_account_signer(6)? {
477 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
478 return Err(InstructionError::MissingRequiredSignature);
479 }
480 } else {
481 ic_logger_msg!(log_collector, "Invalid ProgramData account");
482 return Err(InstructionError::InvalidAccountData);
483 };
484 drop(programdata);
485
486 let buffer = instruction_context.try_borrow_instruction_account(2)?;
488 deploy_program!(
489 invoke_context,
490 &new_program_id,
491 program_id,
492 buffer
493 .get_data()
494 .get(buffer_data_offset..)
495 .ok_or(InstructionError::AccountDataTooSmall)?,
496 clock.slot,
497 invoke_context
498 .get_feature_set()
499 .disable_sbpf_v0_v1_v2_deployment,
500 );
501 drop(buffer);
502
503 let transaction_context = &invoke_context.transaction_context;
504 let instruction_context = transaction_context.get_current_instruction_context()?;
505
506 let mut programdata = instruction_context.try_borrow_instruction_account(0)?;
509 {
510 programdata.set_state(&UpgradeableLoaderState::ProgramData {
511 slot: clock.slot,
512 upgrade_authority_address: authority_key,
513 })?;
514 let dst_slice = programdata
515 .get_data_mut()?
516 .get_mut(
517 programdata_data_offset
518 ..programdata_data_offset.saturating_add(buffer_data_len),
519 )
520 .ok_or(InstructionError::AccountDataTooSmall)?;
521 let buffer = instruction_context.try_borrow_instruction_account(2)?;
522 let src_slice = buffer
523 .get_data()
524 .get(buffer_data_offset..)
525 .ok_or(InstructionError::AccountDataTooSmall)?;
526 dst_slice.copy_from_slice(src_slice);
527 }
528 programdata
529 .get_data_mut()?
530 .get_mut(programdata_data_offset.saturating_add(buffer_data_len)..)
531 .ok_or(InstructionError::AccountDataTooSmall)?
532 .fill(0);
533
534 let mut buffer = instruction_context.try_borrow_instruction_account(2)?;
536 let mut spill = instruction_context.try_borrow_instruction_account(3)?;
537 spill.checked_add_lamports(
538 programdata
539 .get_lamports()
540 .saturating_add(buffer_lamports)
541 .saturating_sub(programdata_balance_required),
542 )?;
543 buffer.set_lamports(0)?;
544 programdata.set_lamports(programdata_balance_required)?;
545 buffer.set_data_length(UpgradeableLoaderState::size_of_buffer(0))?;
546
547 ic_logger_msg!(log_collector, "Upgraded program {:?}", new_program_id);
548 }
549 UpgradeableLoaderInstruction::SetAuthority => {
550 instruction_context.check_number_of_instruction_accounts(2)?;
551 let mut account = instruction_context.try_borrow_instruction_account(0)?;
552 let present_authority_key = instruction_context.get_key_of_instruction_account(1)?;
553 let new_authority = instruction_context.get_key_of_instruction_account(2).ok();
554
555 match account.get_state()? {
556 UpgradeableLoaderState::Buffer { authority_address } => {
557 if new_authority.is_none() {
558 ic_logger_msg!(log_collector, "Buffer authority is not optional");
559 return Err(InstructionError::IncorrectAuthority);
560 }
561 if authority_address.is_none() {
562 ic_logger_msg!(log_collector, "Buffer is immutable");
563 return Err(InstructionError::Immutable);
564 }
565 if authority_address != Some(*present_authority_key) {
566 ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
567 return Err(InstructionError::IncorrectAuthority);
568 }
569 if !instruction_context.is_instruction_account_signer(1)? {
570 ic_logger_msg!(log_collector, "Buffer authority did not sign");
571 return Err(InstructionError::MissingRequiredSignature);
572 }
573 account.set_state(&UpgradeableLoaderState::Buffer {
574 authority_address: new_authority.cloned(),
575 })?;
576 }
577 UpgradeableLoaderState::ProgramData {
578 slot,
579 upgrade_authority_address,
580 } => {
581 if upgrade_authority_address.is_none() {
582 ic_logger_msg!(log_collector, "Program not upgradeable");
583 return Err(InstructionError::Immutable);
584 }
585 if upgrade_authority_address != Some(*present_authority_key) {
586 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
587 return Err(InstructionError::IncorrectAuthority);
588 }
589 if !instruction_context.is_instruction_account_signer(1)? {
590 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
591 return Err(InstructionError::MissingRequiredSignature);
592 }
593 if invoke_context
594 .get_feature_set()
595 .disable_sbpf_v0_v1_v2_deployment
596 && new_authority.is_none()
597 && let Some(program) = account
598 .get_data()
599 .get(UpgradeableLoaderState::size_of_programdata_metadata()..)
600 && let Ok(sbpf_version) = get_sbpf_version(program)
601 && sbpf_version < SBPFVersion::V3
602 {
603 return Err(InstructionError::InvalidAccountData);
604 }
605 account.set_state(&UpgradeableLoaderState::ProgramData {
606 slot,
607 upgrade_authority_address: new_authority.cloned(),
608 })?;
609 }
610 _ => {
611 ic_logger_msg!(log_collector, "Account does not support authorities");
612 return Err(InstructionError::InvalidArgument);
613 }
614 }
615
616 ic_logger_msg!(log_collector, "New authority {:?}", new_authority);
617 }
618 UpgradeableLoaderInstruction::SetAuthorityChecked => {
619 if !invoke_context
620 .get_feature_set()
621 .enable_bpf_loader_set_authority_checked_ix
622 {
623 return Err(InstructionError::InvalidInstructionData);
624 }
625
626 instruction_context.check_number_of_instruction_accounts(3)?;
627 let mut account = instruction_context.try_borrow_instruction_account(0)?;
628 let present_authority_key = instruction_context.get_key_of_instruction_account(1)?;
629 let new_authority_key = instruction_context.get_key_of_instruction_account(2)?;
630
631 match account.get_state()? {
632 UpgradeableLoaderState::Buffer { authority_address } => {
633 if authority_address.is_none() {
634 ic_logger_msg!(log_collector, "Buffer is immutable");
635 return Err(InstructionError::Immutable);
636 }
637 if authority_address != Some(*present_authority_key) {
638 ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
639 return Err(InstructionError::IncorrectAuthority);
640 }
641 if !instruction_context.is_instruction_account_signer(1)? {
642 ic_logger_msg!(log_collector, "Buffer authority did not sign");
643 return Err(InstructionError::MissingRequiredSignature);
644 }
645 if !instruction_context.is_instruction_account_signer(2)? {
646 ic_logger_msg!(log_collector, "New authority did not sign");
647 return Err(InstructionError::MissingRequiredSignature);
648 }
649 account.set_state(&UpgradeableLoaderState::Buffer {
650 authority_address: Some(*new_authority_key),
651 })?;
652 }
653 UpgradeableLoaderState::ProgramData {
654 slot,
655 upgrade_authority_address,
656 } => {
657 if upgrade_authority_address.is_none() {
658 ic_logger_msg!(log_collector, "Program not upgradeable");
659 return Err(InstructionError::Immutable);
660 }
661 if upgrade_authority_address != Some(*present_authority_key) {
662 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
663 return Err(InstructionError::IncorrectAuthority);
664 }
665 if !instruction_context.is_instruction_account_signer(1)? {
666 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
667 return Err(InstructionError::MissingRequiredSignature);
668 }
669 if !instruction_context.is_instruction_account_signer(2)? {
670 ic_logger_msg!(log_collector, "New authority did not sign");
671 return Err(InstructionError::MissingRequiredSignature);
672 }
673 account.set_state(&UpgradeableLoaderState::ProgramData {
674 slot,
675 upgrade_authority_address: Some(*new_authority_key),
676 })?;
677 }
678 _ => {
679 ic_logger_msg!(log_collector, "Account does not support authorities");
680 return Err(InstructionError::InvalidArgument);
681 }
682 }
683
684 ic_logger_msg!(log_collector, "New authority {:?}", new_authority_key);
685 }
686 UpgradeableLoaderInstruction::Close => {
687 instruction_context.check_number_of_instruction_accounts(2)?;
688 if instruction_context.get_index_of_instruction_account_in_transaction(0)?
689 == instruction_context.get_index_of_instruction_account_in_transaction(1)?
690 {
691 ic_logger_msg!(
692 log_collector,
693 "Recipient is the same as the account being closed"
694 );
695 return Err(InstructionError::InvalidArgument);
696 }
697 let mut close_account = instruction_context.try_borrow_instruction_account(0)?;
698 let close_key = *close_account.get_key();
699 let close_account_state = close_account.get_state()?;
700 close_account.set_data_length(UpgradeableLoaderState::size_of_uninitialized())?;
701 match close_account_state {
702 UpgradeableLoaderState::Uninitialized => {
703 let mut recipient_account =
704 instruction_context.try_borrow_instruction_account(1)?;
705 recipient_account.checked_add_lamports(close_account.get_lamports())?;
706 close_account.set_lamports(0)?;
707
708 ic_logger_msg!(log_collector, "Closed Uninitialized {}", close_key);
709 }
710 UpgradeableLoaderState::Buffer { authority_address } => {
711 instruction_context.check_number_of_instruction_accounts(3)?;
712 drop(close_account);
713 common_close_account(&authority_address, &instruction_context, &log_collector)?;
714
715 ic_logger_msg!(log_collector, "Closed Buffer {}", close_key);
716 }
717 UpgradeableLoaderState::ProgramData {
718 slot,
719 upgrade_authority_address: authority_address,
720 } => {
721 instruction_context.check_number_of_instruction_accounts(4)?;
722 drop(close_account);
723 let program_account = instruction_context.try_borrow_instruction_account(3)?;
724 let program_key = *program_account.get_key();
725
726 if !program_account.is_writable() {
727 ic_logger_msg!(log_collector, "Program account is not writable");
728 return Err(InstructionError::InvalidArgument);
729 }
730 if program_account.get_owner() != program_id {
731 ic_logger_msg!(log_collector, "Program account not owned by loader");
732 return Err(InstructionError::IncorrectProgramId);
733 }
734 let clock = invoke_context
735 .environment_config
736 .sysvar_cache()
737 .get_clock()?;
738 if clock.slot == slot {
739 ic_logger_msg!(log_collector, "Program was deployed in this block already");
740 return Err(InstructionError::InvalidArgument);
741 }
742
743 match program_account.get_state()? {
744 UpgradeableLoaderState::Program {
745 programdata_address,
746 } => {
747 if programdata_address != close_key {
748 ic_logger_msg!(
749 log_collector,
750 "ProgramData account does not match ProgramData account"
751 );
752 return Err(InstructionError::InvalidArgument);
753 }
754
755 drop(program_account);
756 common_close_account(
757 &authority_address,
758 &instruction_context,
759 &log_collector,
760 )?;
761 let clock = invoke_context
762 .environment_config
763 .sysvar_cache()
764 .get_clock()?;
765 invoke_context
766 .program_cache_for_tx_batch
767 .store_modified_entry(
768 program_key,
769 Arc::new(ProgramCacheEntry::new_closed_tombstone(
770 clock.slot,
771 ProgramCacheEntryOwner::LoaderV3,
772 )),
773 );
774 }
775 _ => {
776 ic_logger_msg!(log_collector, "Invalid Program account");
777 return Err(InstructionError::InvalidArgument);
778 }
779 }
780
781 ic_logger_msg!(log_collector, "Closed Program {}", program_key);
782 }
783 _ => {
784 ic_logger_msg!(log_collector, "Account does not support closing");
785 return Err(InstructionError::InvalidArgument);
786 }
787 }
788 }
789 UpgradeableLoaderInstruction::ExtendProgram { additional_bytes } => {
790 common_extend_program(invoke_context, additional_bytes, false)?;
791 }
792 }
793
794 Ok(())
795}
796
797fn common_extend_program(
798 invoke_context: &mut InvokeContext,
799 additional_bytes: u32,
800 check_authority: bool,
801) -> Result<(), InstructionError> {
802 let log_collector = invoke_context.get_log_collector();
803 let transaction_context = &invoke_context.transaction_context;
804 let instruction_context = transaction_context.get_current_instruction_context()?;
805 let program_id = instruction_context.get_program_key()?;
806
807 const PROGRAM_DATA_ACCOUNT_INDEX: IndexOfAccount = 0;
808 const PROGRAM_ACCOUNT_INDEX: IndexOfAccount = 1;
809 const AUTHORITY_ACCOUNT_INDEX: IndexOfAccount = 2;
810 let optional_payer_account_index = if check_authority { 4 } else { 3 };
812
813 if additional_bytes == 0 {
814 ic_logger_msg!(log_collector, "Additional bytes must be greater than 0");
815 return Err(InstructionError::InvalidInstructionData);
816 }
817
818 let programdata_account =
819 instruction_context.try_borrow_instruction_account(PROGRAM_DATA_ACCOUNT_INDEX)?;
820 let programdata_key = *programdata_account.get_key();
821
822 if program_id != programdata_account.get_owner() {
823 ic_logger_msg!(log_collector, "ProgramData owner is invalid");
824 return Err(InstructionError::InvalidAccountOwner);
825 }
826 if !programdata_account.is_writable() {
827 ic_logger_msg!(log_collector, "ProgramData is not writable");
828 return Err(InstructionError::InvalidArgument);
829 }
830
831 let program_account =
832 instruction_context.try_borrow_instruction_account(PROGRAM_ACCOUNT_INDEX)?;
833 if !program_account.is_writable() {
834 ic_logger_msg!(log_collector, "Program account is not writable");
835 return Err(InstructionError::InvalidArgument);
836 }
837 if program_account.get_owner() != program_id {
838 ic_logger_msg!(log_collector, "Program account not owned by loader");
839 return Err(InstructionError::InvalidAccountOwner);
840 }
841 let program_key = *program_account.get_key();
842 match program_account.get_state()? {
843 UpgradeableLoaderState::Program {
844 programdata_address,
845 } => {
846 if programdata_address != programdata_key {
847 ic_logger_msg!(
848 log_collector,
849 "Program account does not match ProgramData account"
850 );
851 return Err(InstructionError::InvalidArgument);
852 }
853 }
854 _ => {
855 ic_logger_msg!(log_collector, "Invalid Program account");
856 return Err(InstructionError::InvalidAccountData);
857 }
858 }
859 drop(program_account);
860
861 let old_len = programdata_account.get_data().len();
862 let new_len = old_len.saturating_add(additional_bytes as usize);
863 if new_len > MAX_PERMITTED_DATA_LENGTH as usize {
864 ic_logger_msg!(
865 log_collector,
866 "Extended ProgramData length of {} bytes exceeds max account data length of {} bytes",
867 new_len,
868 MAX_PERMITTED_DATA_LENGTH
869 );
870 return Err(InstructionError::InvalidRealloc);
871 }
872
873 if invoke_context
874 .get_feature_set()
875 .loader_v3_minimum_extend_program_size
876 {
877 let headroom = (MAX_PERMITTED_DATA_LENGTH as usize).saturating_sub(old_len);
883 if additional_bytes < MINIMUM_EXTEND_PROGRAM_BYTES
884 && (additional_bytes as usize) != headroom
885 {
886 ic_logger_msg!(
887 log_collector,
888 "ExtendProgram requires a minimum of {} additional bytes or to extend to maximum \
889 size, but only {} were requested",
890 MINIMUM_EXTEND_PROGRAM_BYTES,
891 additional_bytes,
892 );
893 return Err(InstructionError::InvalidArgument);
894 }
895 }
896
897 let clock_slot = invoke_context
898 .environment_config
899 .sysvar_cache()
900 .get_clock()
901 .map(|clock| clock.slot)?;
902
903 let upgrade_authority_address = if let UpgradeableLoaderState::ProgramData {
904 slot,
905 upgrade_authority_address,
906 } = programdata_account.get_state()?
907 {
908 if clock_slot == slot {
909 ic_logger_msg!(log_collector, "Program was extended in this block already");
910 return Err(InstructionError::InvalidArgument);
911 }
912
913 if upgrade_authority_address.is_none() {
914 ic_logger_msg!(
915 log_collector,
916 "Cannot extend ProgramData accounts that are not upgradeable"
917 );
918 return Err(InstructionError::Immutable);
919 }
920
921 if check_authority {
922 let authority_key =
923 Some(*instruction_context.get_key_of_instruction_account(AUTHORITY_ACCOUNT_INDEX)?);
924 if upgrade_authority_address != authority_key {
925 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
926 return Err(InstructionError::IncorrectAuthority);
927 }
928 if !instruction_context.is_instruction_account_signer(AUTHORITY_ACCOUNT_INDEX)? {
929 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
930 return Err(InstructionError::MissingRequiredSignature);
931 }
932 }
933
934 upgrade_authority_address
935 } else {
936 ic_logger_msg!(log_collector, "ProgramData state is invalid");
937 return Err(InstructionError::InvalidAccountData);
938 };
939
940 let required_payment = {
941 let balance = programdata_account.get_lamports();
942 let rent = invoke_context
943 .environment_config
944 .sysvar_cache()
945 .get_rent()?;
946 let min_balance = rent.minimum_balance(new_len).max(1);
947 min_balance.saturating_sub(balance)
948 };
949
950 drop(programdata_account);
952
953 let program_id = *program_id;
955 if required_payment > 0 {
956 let payer_key =
957 *instruction_context.get_key_of_instruction_account(optional_payer_account_index)?;
958
959 invoke_context.native_invoke_signed(
960 system_instruction::transfer(&payer_key, &programdata_key, required_payment),
961 &[],
962 )?;
963 }
964
965 let transaction_context = &invoke_context.transaction_context;
966 let instruction_context = transaction_context.get_current_instruction_context()?;
967 let mut programdata_account =
968 instruction_context.try_borrow_instruction_account(PROGRAM_DATA_ACCOUNT_INDEX)?;
969 programdata_account.set_data_length(new_len)?;
970
971 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
972
973 deploy_program!(
974 invoke_context,
975 &program_key,
976 &program_id,
977 programdata_account
978 .get_data()
979 .get(programdata_data_offset..)
980 .ok_or(InstructionError::AccountDataTooSmall)?,
981 clock_slot,
982 false, );
984 drop(programdata_account);
985
986 let mut programdata_account =
987 instruction_context.try_borrow_instruction_account(PROGRAM_DATA_ACCOUNT_INDEX)?;
988 programdata_account.set_state(&UpgradeableLoaderState::ProgramData {
989 slot: clock_slot,
990 upgrade_authority_address,
991 })?;
992
993 ic_logger_msg!(
994 log_collector,
995 "Extended ProgramData account by {} bytes",
996 additional_bytes
997 );
998
999 Ok(())
1000}
1001
1002fn common_close_account(
1003 authority_address: &Option<Pubkey>,
1004 instruction_context: &InstructionContext,
1005 log_collector: &Option<Rc<RefCell<LogCollector>>>,
1006) -> Result<(), InstructionError> {
1007 if authority_address.is_none() {
1008 ic_logger_msg!(log_collector, "Account is immutable");
1009 return Err(InstructionError::Immutable);
1010 }
1011 if *authority_address != Some(*instruction_context.get_key_of_instruction_account(2)?) {
1012 ic_logger_msg!(log_collector, "Incorrect authority provided");
1013 return Err(InstructionError::IncorrectAuthority);
1014 }
1015 if !instruction_context.is_instruction_account_signer(2)? {
1016 ic_logger_msg!(log_collector, "Authority did not sign");
1017 return Err(InstructionError::MissingRequiredSignature);
1018 }
1019
1020 let mut close_account = instruction_context.try_borrow_instruction_account(0)?;
1021 let mut recipient_account = instruction_context.try_borrow_instruction_account(1)?;
1022
1023 recipient_account.checked_add_lamports(close_account.get_lamports())?;
1024 close_account.set_lamports(0)?;
1025 close_account.set_state(&UpgradeableLoaderState::Uninitialized)?;
1026 Ok(())
1027}
1028
1029#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
1030mod test_utils {
1031 #[cfg(all(feature = "svm-internal", feature = "metrics"))]
1032 use solana_program_runtime::program_metrics::LoadProgramMetrics;
1033 #[cfg(feature = "svm-internal")]
1034 use {
1035 super::*, solana_account::ReadableAccount,
1036 solana_program_runtime::loaded_programs::ProgramRuntimeEnvironment,
1037 solana_syscalls::create_program_runtime_environment,
1038 };
1039
1040 #[cfg(feature = "svm-internal")]
1041 fn check_loader_id(id: &Pubkey) -> bool {
1042 bpf_loader::check_id(id)
1043 || bpf_loader_deprecated::check_id(id)
1044 || bpf_loader_upgradeable::check_id(id)
1045 }
1046
1047 #[cfg(feature = "svm-internal")]
1048 #[cfg_attr(feature = "svm-internal", qualifiers(pub))]
1049 fn load_all_invoked_programs(invoke_context: &mut InvokeContext) {
1050 let program_runtime_environment = create_program_runtime_environment(
1051 invoke_context.get_feature_set(),
1052 invoke_context.get_compute_budget(),
1053 false, false, )
1056 .unwrap();
1057 let num_accounts = invoke_context.transaction_context.get_number_of_accounts();
1058 for index in 0..num_accounts {
1059 let account = invoke_context
1060 .transaction_context
1061 .accounts()
1062 .try_borrow(index)
1063 .expect("Failed to get the account");
1064
1065 let owner = account.owner();
1066 if check_loader_id(owner) {
1067 let programdata_data_offset = 0;
1068 let pubkey = invoke_context
1069 .transaction_context
1070 .get_key_of_account_at_index(index)
1071 .expect("Failed to get account key");
1072
1073 let programdata = account
1074 .data()
1075 .get(programdata_data_offset.min(account.data().len())..)
1076 .unwrap();
1077 let loaded_program = ProgramCacheEntry::load(
1078 owner,
1079 ProgramRuntimeEnvironment::clone(&program_runtime_environment),
1080 0,
1081 programdata,
1082 #[cfg(feature = "metrics")]
1083 &mut LoadProgramMetrics::default(),
1084 )
1085 .map_err(|_| InstructionError::InvalidAccountData);
1086 if let Ok(loaded_program) = loaded_program {
1087 invoke_context
1088 .program_cache_for_tx_batch
1089 .store_modified_entry(*pubkey, Arc::new(loaded_program));
1090 }
1091 }
1092 }
1093 }
1094}
1095
1096#[cfg(test)]
1097mod tests {
1098 use {
1099 super::*,
1100 assert_matches::assert_matches,
1101 rand::Rng,
1102 solana_account::{
1103 AccountSharedData, ReadableAccount, WritableAccount,
1104 create_account_shared_data_for_test as create_account_for_test, state_traits::StateMut,
1105 },
1106 solana_clock::Clock,
1107 solana_epoch_schedule::EpochSchedule,
1108 solana_instruction::{AccountMeta, error::InstructionError},
1109 solana_program_runtime::{
1110 invoke_context::mock_process_instruction, loaded_programs::ProgramRuntimeEnvironment,
1111 program_metrics::ProgramStatistics, vm::calculate_heap_cost, with_mock_invoke_context,
1112 },
1113 solana_pubkey::Pubkey,
1114 solana_rent::Rent,
1115 solana_sbpf::program::{BuiltinFunctionDefinition, BuiltinProgram},
1116 solana_sdk_ids::{system_program, sysvar},
1117 solana_svm_type_overrides::sync::atomic::{AtomicU64, Ordering},
1118 std::{fs::File, io::Read, ops::Range},
1119 };
1120
1121 #[cfg(feature = "shuttle-test")]
1127 const MOCK_PROCESS_RANDOM_ITERATIONS: usize = 10;
1128
1129 fn process_instruction_with_setup(
1152 program_id: &Pubkey,
1153 instruction_data: &[u8],
1154 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
1155 instruction_accounts: Vec<AccountMeta>,
1156 expected_result: Result<(), InstructionError>,
1157 setup: fn(&mut InvokeContext),
1158 ) -> Vec<AccountSharedData> {
1159 #[cfg(feature = "shuttle-test")]
1160 {
1161 let program_id = *program_id;
1162 let instruction_data = instruction_data.to_vec();
1163 let result = shuttle::sync::Arc::new(shuttle::sync::Mutex::new(None));
1164 let result_for_test = shuttle::sync::Arc::clone(&result);
1165 shuttle::check_random(
1166 move || {
1167 let accounts = mock_process_instruction(
1168 &program_id,
1169 &instruction_data,
1170 transaction_accounts.clone(),
1171 instruction_accounts.clone(),
1172 expected_result.clone(),
1173 Entrypoint::register,
1174 setup,
1175 |_invoke_context| {},
1176 );
1177 *result_for_test.lock().unwrap() = Some(accounts);
1178 },
1179 MOCK_PROCESS_RANDOM_ITERATIONS,
1180 );
1181
1182 let mut result = match shuttle::sync::Arc::try_unwrap(result) {
1185 Ok(result) => result,
1186 Err(_) => panic!("shuttle test result still has outstanding references"),
1187 };
1188 result
1189 .get_mut()
1190 .unwrap()
1191 .take()
1192 .expect("shuttle test did not produce a result")
1193 }
1194
1195 #[cfg(not(feature = "shuttle-test"))]
1196 mock_process_instruction(
1197 program_id,
1198 instruction_data,
1199 transaction_accounts,
1200 instruction_accounts,
1201 expected_result,
1202 Entrypoint::register,
1203 setup,
1204 |_invoke_context| {},
1205 )
1206 }
1207
1208 fn process_instruction(
1209 program_id: &Pubkey,
1210 instruction_data: &[u8],
1211 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
1212 instruction_accounts: Vec<AccountMeta>,
1213 expected_result: Result<(), InstructionError>,
1214 ) -> Vec<AccountSharedData> {
1215 process_instruction_with_setup(
1216 program_id,
1217 instruction_data,
1218 transaction_accounts,
1219 instruction_accounts,
1220 expected_result,
1221 |invoke_context| {
1222 test_utils::load_all_invoked_programs(invoke_context);
1223 },
1224 )
1225 }
1226
1227 fn load_program_account_from_elf(loader_id: &Pubkey, path: &str) -> AccountSharedData {
1228 let mut file = File::open(path).expect("file open failed");
1229 let mut elf = Vec::new();
1230 file.read_to_end(&mut elf).unwrap();
1231 let rent = Rent::default();
1232 let mut program_account =
1233 AccountSharedData::new(rent.minimum_balance(elf.len()), 0, loader_id);
1234 program_account.set_data(elf);
1235 program_account.set_executable(true);
1236 program_account
1237 }
1238
1239 #[test]
1240 fn test_bpf_loader_invoke_main() {
1241 let loader_id = bpf_loader::id();
1242 let program_id = Pubkey::new_unique();
1243 let program_account =
1244 load_program_account_from_elf(&loader_id, "test_elfs/out/sbpfv3_return_ok.so");
1245 let parameter_id = Pubkey::new_unique();
1246 let parameter_account = AccountSharedData::new(1, 0, &loader_id);
1247 let parameter_meta = AccountMeta {
1248 pubkey: parameter_id,
1249 is_signer: false,
1250 is_writable: false,
1251 };
1252
1253 process_instruction(
1255 &loader_id,
1256 &[],
1257 Vec::new(),
1258 Vec::new(),
1259 Err(InstructionError::UnsupportedProgramId),
1260 );
1261
1262 process_instruction(
1264 &program_id,
1265 &[],
1266 vec![(program_id, program_account.clone())],
1267 Vec::new(),
1268 Ok(()),
1269 );
1270
1271 process_instruction(
1273 &program_id,
1274 &[],
1275 vec![
1276 (program_id, program_account.clone()),
1277 (parameter_id, parameter_account.clone()),
1278 ],
1279 vec![parameter_meta.clone()],
1280 Ok(()),
1281 );
1282
1283 process_instruction(
1285 &program_id,
1286 &[],
1287 vec![
1288 (program_id, program_account.clone()),
1289 (parameter_id, parameter_account.clone()),
1290 ],
1291 vec![parameter_meta.clone(), parameter_meta],
1292 Ok(()),
1293 );
1294
1295 process_instruction_with_setup(
1297 &program_id,
1298 &[],
1299 vec![(program_id, program_account)],
1300 Vec::new(),
1301 Err(InstructionError::ProgramFailedToComplete),
1302 |invoke_context| {
1303 invoke_context.compute_meter.mock_set_remaining(0);
1304 test_utils::load_all_invoked_programs(invoke_context);
1305 },
1306 );
1307
1308 process_instruction_with_setup(
1310 &program_id,
1311 &[],
1312 vec![(program_id, parameter_account.clone())],
1313 Vec::new(),
1314 Err(InstructionError::UnsupportedProgramId),
1315 |invoke_context| {
1316 test_utils::load_all_invoked_programs(invoke_context);
1317 },
1318 );
1319 process_instruction(
1320 &program_id,
1321 &[],
1322 vec![(program_id, parameter_account)],
1323 Vec::new(),
1324 Err(InstructionError::UnsupportedProgramId),
1325 );
1326 }
1327
1328 #[test]
1329 fn test_bpf_loader_serialize_unaligned() {
1330 let loader_id = bpf_loader_deprecated::id();
1331 let program_id = Pubkey::new_unique();
1332 let program_account =
1333 load_program_account_from_elf(&loader_id, "test_elfs/out/noop_unaligned.so");
1334 let parameter_id = Pubkey::new_unique();
1335 let parameter_account = AccountSharedData::new(1, 0, &loader_id);
1336 let parameter_meta = AccountMeta {
1337 pubkey: parameter_id,
1338 is_signer: false,
1339 is_writable: false,
1340 };
1341
1342 process_instruction(
1344 &program_id,
1345 &[],
1346 vec![
1347 (program_id, program_account.clone()),
1348 (parameter_id, parameter_account.clone()),
1349 ],
1350 vec![parameter_meta.clone()],
1351 Ok(()),
1352 );
1353
1354 process_instruction(
1356 &program_id,
1357 &[],
1358 vec![
1359 (program_id, program_account),
1360 (parameter_id, parameter_account),
1361 ],
1362 vec![parameter_meta.clone(), parameter_meta],
1363 Ok(()),
1364 );
1365 }
1366
1367 #[test]
1368 fn test_bpf_loader_serialize_aligned() {
1369 let loader_id = bpf_loader::id();
1370 let program_id = Pubkey::new_unique();
1371 let program_account =
1372 load_program_account_from_elf(&loader_id, "test_elfs/out/noop_aligned.so");
1373 let parameter_id = Pubkey::new_unique();
1374 let parameter_account = AccountSharedData::new(1, 0, &loader_id);
1375 let parameter_meta = AccountMeta {
1376 pubkey: parameter_id,
1377 is_signer: false,
1378 is_writable: false,
1379 };
1380
1381 process_instruction(
1383 &program_id,
1384 &[],
1385 vec![
1386 (program_id, program_account.clone()),
1387 (parameter_id, parameter_account.clone()),
1388 ],
1389 vec![parameter_meta.clone()],
1390 Ok(()),
1391 );
1392
1393 process_instruction(
1395 &program_id,
1396 &[],
1397 vec![
1398 (program_id, program_account),
1399 (parameter_id, parameter_account),
1400 ],
1401 vec![parameter_meta.clone(), parameter_meta],
1402 Ok(()),
1403 );
1404 }
1405
1406 #[test]
1407 fn test_bpf_loader_upgradeable_initialize_buffer() {
1408 let loader_id = bpf_loader_upgradeable::id();
1409 let buffer_address = Pubkey::new_unique();
1410 let buffer_account =
1411 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1412 let authority_address = Pubkey::new_unique();
1413 let authority_account =
1414 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1415 let instruction_data =
1416 bincode::serialize(&UpgradeableLoaderInstruction::InitializeBuffer).unwrap();
1417 let instruction_accounts = vec![
1418 AccountMeta {
1419 pubkey: buffer_address,
1420 is_signer: false,
1421 is_writable: true,
1422 },
1423 AccountMeta {
1424 pubkey: authority_address,
1425 is_signer: false,
1426 is_writable: false,
1427 },
1428 ];
1429
1430 let accounts = process_instruction(
1432 &loader_id,
1433 &instruction_data,
1434 vec![
1435 (buffer_address, buffer_account),
1436 (authority_address, authority_account),
1437 ],
1438 instruction_accounts.clone(),
1439 Ok(()),
1440 );
1441 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1442 assert_eq!(
1443 state,
1444 UpgradeableLoaderState::Buffer {
1445 authority_address: Some(authority_address)
1446 }
1447 );
1448
1449 let accounts = process_instruction(
1451 &loader_id,
1452 &instruction_data,
1453 vec![
1454 (buffer_address, accounts.first().unwrap().clone()),
1455 (authority_address, accounts.get(1).unwrap().clone()),
1456 ],
1457 instruction_accounts,
1458 Err(InstructionError::AccountAlreadyInitialized),
1459 );
1460 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1461 assert_eq!(
1462 state,
1463 UpgradeableLoaderState::Buffer {
1464 authority_address: Some(authority_address)
1465 }
1466 );
1467 }
1468
1469 #[test]
1470 fn test_bpf_loader_upgradeable_write() {
1471 let loader_id = bpf_loader_upgradeable::id();
1472 let buffer_address = Pubkey::new_unique();
1473 let mut buffer_account =
1474 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1475 let instruction_accounts = vec![
1476 AccountMeta {
1477 pubkey: buffer_address,
1478 is_signer: false,
1479 is_writable: true,
1480 },
1481 AccountMeta {
1482 pubkey: buffer_address,
1483 is_signer: true,
1484 is_writable: false,
1485 },
1486 ];
1487
1488 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1490 offset: 0,
1491 bytes: vec![42; 9],
1492 })
1493 .unwrap();
1494 process_instruction(
1495 &loader_id,
1496 &instruction,
1497 vec![(buffer_address, buffer_account.clone())],
1498 instruction_accounts.clone(),
1499 Err(InstructionError::InvalidAccountData),
1500 );
1501
1502 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1504 offset: 0,
1505 bytes: vec![42; 9],
1506 })
1507 .unwrap();
1508 buffer_account
1509 .set_state(&UpgradeableLoaderState::Buffer {
1510 authority_address: Some(buffer_address),
1511 })
1512 .unwrap();
1513 let accounts = process_instruction(
1514 &loader_id,
1515 &instruction,
1516 vec![(buffer_address, buffer_account.clone())],
1517 instruction_accounts.clone(),
1518 Ok(()),
1519 );
1520 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1521 assert_eq!(
1522 state,
1523 UpgradeableLoaderState::Buffer {
1524 authority_address: Some(buffer_address)
1525 }
1526 );
1527 assert_eq!(
1528 &accounts
1529 .first()
1530 .unwrap()
1531 .data()
1532 .get(UpgradeableLoaderState::size_of_buffer_metadata()..)
1533 .unwrap(),
1534 &[42; 9]
1535 );
1536
1537 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1539 offset: 3,
1540 bytes: vec![42; 6],
1541 })
1542 .unwrap();
1543 let mut buffer_account =
1544 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1545 buffer_account
1546 .set_state(&UpgradeableLoaderState::Buffer {
1547 authority_address: Some(buffer_address),
1548 })
1549 .unwrap();
1550 let accounts = process_instruction(
1551 &loader_id,
1552 &instruction,
1553 vec![(buffer_address, buffer_account.clone())],
1554 instruction_accounts.clone(),
1555 Ok(()),
1556 );
1557 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1558 assert_eq!(
1559 state,
1560 UpgradeableLoaderState::Buffer {
1561 authority_address: Some(buffer_address)
1562 }
1563 );
1564 assert_eq!(
1565 &accounts
1566 .first()
1567 .unwrap()
1568 .data()
1569 .get(UpgradeableLoaderState::size_of_buffer_metadata()..)
1570 .unwrap(),
1571 &[0, 0, 0, 42, 42, 42, 42, 42, 42]
1572 );
1573
1574 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1576 offset: 0,
1577 bytes: vec![42; 10],
1578 })
1579 .unwrap();
1580 buffer_account
1581 .set_state(&UpgradeableLoaderState::Buffer {
1582 authority_address: Some(buffer_address),
1583 })
1584 .unwrap();
1585 process_instruction(
1586 &loader_id,
1587 &instruction,
1588 vec![(buffer_address, buffer_account.clone())],
1589 instruction_accounts.clone(),
1590 Err(InstructionError::AccountDataTooSmall),
1591 );
1592
1593 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1595 offset: 1,
1596 bytes: vec![42; 9],
1597 })
1598 .unwrap();
1599 buffer_account
1600 .set_state(&UpgradeableLoaderState::Buffer {
1601 authority_address: Some(buffer_address),
1602 })
1603 .unwrap();
1604 process_instruction(
1605 &loader_id,
1606 &instruction,
1607 vec![(buffer_address, buffer_account.clone())],
1608 instruction_accounts.clone(),
1609 Err(InstructionError::AccountDataTooSmall),
1610 );
1611
1612 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1614 offset: 0,
1615 bytes: vec![42; 9],
1616 })
1617 .unwrap();
1618 buffer_account
1619 .set_state(&UpgradeableLoaderState::Buffer {
1620 authority_address: Some(buffer_address),
1621 })
1622 .unwrap();
1623 process_instruction(
1624 &loader_id,
1625 &instruction,
1626 vec![(buffer_address, buffer_account.clone())],
1627 vec![
1628 AccountMeta {
1629 pubkey: buffer_address,
1630 is_signer: false,
1631 is_writable: false,
1632 },
1633 AccountMeta {
1634 pubkey: buffer_address,
1635 is_signer: false,
1636 is_writable: false,
1637 },
1638 ],
1639 Err(InstructionError::MissingRequiredSignature),
1640 );
1641
1642 let authority_address = Pubkey::new_unique();
1644 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1645 offset: 1,
1646 bytes: vec![42; 9],
1647 })
1648 .unwrap();
1649 buffer_account
1650 .set_state(&UpgradeableLoaderState::Buffer {
1651 authority_address: Some(buffer_address),
1652 })
1653 .unwrap();
1654 process_instruction(
1655 &loader_id,
1656 &instruction,
1657 vec![
1658 (buffer_address, buffer_account.clone()),
1659 (authority_address, buffer_account.clone()),
1660 ],
1661 vec![
1662 AccountMeta {
1663 pubkey: buffer_address,
1664 is_signer: false,
1665 is_writable: false,
1666 },
1667 AccountMeta {
1668 pubkey: authority_address,
1669 is_signer: false,
1670 is_writable: false,
1671 },
1672 ],
1673 Err(InstructionError::IncorrectAuthority),
1674 );
1675
1676 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1678 offset: 1,
1679 bytes: vec![42; 9],
1680 })
1681 .unwrap();
1682 buffer_account
1683 .set_state(&UpgradeableLoaderState::Buffer {
1684 authority_address: None,
1685 })
1686 .unwrap();
1687 process_instruction(
1688 &loader_id,
1689 &instruction,
1690 vec![(buffer_address, buffer_account.clone())],
1691 instruction_accounts,
1692 Err(InstructionError::Immutable),
1693 );
1694 }
1695
1696 fn truncate_data(account: &mut AccountSharedData, len: usize) {
1697 let mut data = account.data().to_vec();
1698 data.truncate(len);
1699 account.set_data(data);
1700 }
1701
1702 #[test]
1703 fn test_bpf_loader_upgradeable_upgrade() {
1704 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
1705 let mut elf_orig = Vec::new();
1706 file.read_to_end(&mut elf_orig).unwrap();
1707 let mut file = File::open("test_elfs/out/sbpfv3_return_err.so").expect("file open failed");
1708 let mut elf_new = Vec::new();
1709 file.read_to_end(&mut elf_new).unwrap();
1710 assert_ne!(elf_orig.len(), elf_new.len());
1711 const SLOT: u64 = 42;
1712 let buffer_address = Pubkey::new_unique();
1713 let upgrade_authority_address = Pubkey::new_unique();
1714
1715 fn get_accounts(
1716 buffer_address: &Pubkey,
1717 buffer_authority: &Pubkey,
1718 upgrade_authority_address: &Pubkey,
1719 elf_orig: &[u8],
1720 elf_new: &[u8],
1721 ) -> (Vec<(Pubkey, AccountSharedData)>, Vec<AccountMeta>) {
1722 let loader_id = bpf_loader_upgradeable::id();
1723 let program_address = Pubkey::new_unique();
1724 let spill_address = Pubkey::new_unique();
1725 let rent = Rent::default();
1726 let min_program_balance =
1727 1.max(rent.minimum_balance(UpgradeableLoaderState::size_of_program()));
1728 let min_programdata_balance = 1.max(rent.minimum_balance(
1729 UpgradeableLoaderState::size_of_programdata(elf_orig.len().max(elf_new.len())),
1730 ));
1731 let (programdata_address, _) =
1732 Pubkey::find_program_address(&[program_address.as_ref()], &loader_id);
1733 let mut buffer_account = AccountSharedData::new(
1734 1,
1735 UpgradeableLoaderState::size_of_buffer(elf_new.len()),
1736 &bpf_loader_upgradeable::id(),
1737 );
1738 buffer_account
1739 .set_state(&UpgradeableLoaderState::Buffer {
1740 authority_address: Some(*buffer_authority),
1741 })
1742 .unwrap();
1743 buffer_account
1744 .data_as_mut_slice()
1745 .get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
1746 .unwrap()
1747 .copy_from_slice(elf_new);
1748 let mut programdata_account = AccountSharedData::new(
1749 min_programdata_balance,
1750 UpgradeableLoaderState::size_of_programdata(elf_orig.len().max(elf_new.len())),
1751 &bpf_loader_upgradeable::id(),
1752 );
1753 programdata_account
1754 .set_state(&UpgradeableLoaderState::ProgramData {
1755 slot: SLOT,
1756 upgrade_authority_address: Some(*upgrade_authority_address),
1757 })
1758 .unwrap();
1759 let mut program_account = AccountSharedData::new(
1760 min_program_balance,
1761 UpgradeableLoaderState::size_of_program(),
1762 &bpf_loader_upgradeable::id(),
1763 );
1764 program_account.set_executable(true);
1765 program_account
1766 .set_state(&UpgradeableLoaderState::Program {
1767 programdata_address,
1768 })
1769 .unwrap();
1770 let spill_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
1771 let rent_account = create_account_for_test(&rent);
1772 let clock_account = create_account_for_test(&Clock {
1773 slot: SLOT.saturating_add(1),
1774 ..Clock::default()
1775 });
1776 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
1777 let transaction_accounts = vec![
1778 (programdata_address, programdata_account),
1779 (program_address, program_account),
1780 (*buffer_address, buffer_account),
1781 (spill_address, spill_account),
1782 (sysvar::rent::id(), rent_account),
1783 (sysvar::clock::id(), clock_account),
1784 (*upgrade_authority_address, upgrade_authority_account),
1785 ];
1786 let instruction_accounts = vec![
1787 AccountMeta {
1788 pubkey: programdata_address,
1789 is_signer: false,
1790 is_writable: true,
1791 },
1792 AccountMeta {
1793 pubkey: program_address,
1794 is_signer: false,
1795 is_writable: true,
1796 },
1797 AccountMeta {
1798 pubkey: *buffer_address,
1799 is_signer: false,
1800 is_writable: true,
1801 },
1802 AccountMeta {
1803 pubkey: spill_address,
1804 is_signer: false,
1805 is_writable: true,
1806 },
1807 AccountMeta {
1808 pubkey: sysvar::rent::id(),
1809 is_signer: false,
1810 is_writable: false,
1811 },
1812 AccountMeta {
1813 pubkey: sysvar::clock::id(),
1814 is_signer: false,
1815 is_writable: false,
1816 },
1817 AccountMeta {
1818 pubkey: *upgrade_authority_address,
1819 is_signer: true,
1820 is_writable: false,
1821 },
1822 ];
1823 (transaction_accounts, instruction_accounts)
1824 }
1825
1826 fn process_instruction(
1827 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
1828 instruction_accounts: Vec<AccountMeta>,
1829 expected_result: Result<(), InstructionError>,
1830 ) -> Vec<AccountSharedData> {
1831 let instruction_data =
1832 bincode::serialize(&UpgradeableLoaderInstruction::Upgrade).unwrap();
1833 process_instruction_with_setup(
1834 &bpf_loader_upgradeable::id(),
1835 &instruction_data,
1836 transaction_accounts,
1837 instruction_accounts,
1838 expected_result,
1839 |_invoke_context| {},
1840 )
1841 }
1842
1843 let (transaction_accounts, instruction_accounts) = get_accounts(
1845 &buffer_address,
1846 &upgrade_authority_address,
1847 &upgrade_authority_address,
1848 &elf_orig,
1849 &elf_new,
1850 );
1851 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
1852 let min_programdata_balance = Rent::default().minimum_balance(
1853 UpgradeableLoaderState::size_of_programdata(elf_orig.len().max(elf_new.len())),
1854 );
1855 assert_eq!(
1856 min_programdata_balance,
1857 accounts.first().unwrap().lamports()
1858 );
1859 assert_eq!(0, accounts.get(2).unwrap().lamports());
1860 assert_eq!(1, accounts.get(3).unwrap().lamports());
1861 assert_eq!(
1862 UpgradeableLoaderState::size_of_buffer(0),
1863 accounts.get(2).unwrap().data().len()
1864 );
1865 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1866 assert_eq!(
1867 state,
1868 UpgradeableLoaderState::ProgramData {
1869 slot: SLOT.saturating_add(1),
1870 upgrade_authority_address: Some(upgrade_authority_address)
1871 }
1872 );
1873 for (i, byte) in accounts
1874 .first()
1875 .unwrap()
1876 .data()
1877 .get(
1878 UpgradeableLoaderState::size_of_programdata_metadata()
1879 ..UpgradeableLoaderState::size_of_programdata(elf_new.len()),
1880 )
1881 .unwrap()
1882 .iter()
1883 .enumerate()
1884 {
1885 assert_eq!(*elf_new.get(i).unwrap(), *byte);
1886 }
1887
1888 let (mut transaction_accounts, instruction_accounts) = get_accounts(
1890 &buffer_address,
1891 &upgrade_authority_address,
1892 &upgrade_authority_address,
1893 &elf_orig,
1894 &elf_new,
1895 );
1896 transaction_accounts
1897 .get_mut(0)
1898 .unwrap()
1899 .1
1900 .set_state(&UpgradeableLoaderState::ProgramData {
1901 slot: SLOT,
1902 upgrade_authority_address: None,
1903 })
1904 .unwrap();
1905 process_instruction(
1906 transaction_accounts,
1907 instruction_accounts,
1908 Err(InstructionError::Immutable),
1909 );
1910
1911 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
1913 &buffer_address,
1914 &upgrade_authority_address,
1915 &upgrade_authority_address,
1916 &elf_orig,
1917 &elf_new,
1918 );
1919 let invalid_upgrade_authority_address = Pubkey::new_unique();
1920 transaction_accounts.get_mut(6).unwrap().0 = invalid_upgrade_authority_address;
1921 instruction_accounts.get_mut(6).unwrap().pubkey = invalid_upgrade_authority_address;
1922 process_instruction(
1923 transaction_accounts,
1924 instruction_accounts,
1925 Err(InstructionError::IncorrectAuthority),
1926 );
1927
1928 let (transaction_accounts, mut instruction_accounts) = get_accounts(
1930 &buffer_address,
1931 &upgrade_authority_address,
1932 &upgrade_authority_address,
1933 &elf_orig,
1934 &elf_new,
1935 );
1936 instruction_accounts.get_mut(6).unwrap().is_signer = false;
1937 process_instruction(
1938 transaction_accounts,
1939 instruction_accounts,
1940 Err(InstructionError::MissingRequiredSignature),
1941 );
1942
1943 let (transaction_accounts, mut instruction_accounts) = get_accounts(
1945 &buffer_address,
1946 &upgrade_authority_address,
1947 &upgrade_authority_address,
1948 &elf_orig,
1949 &elf_new,
1950 );
1951 *instruction_accounts.get_mut(3).unwrap() = instruction_accounts.get(2).unwrap().clone();
1952 process_instruction(
1953 transaction_accounts,
1954 instruction_accounts,
1955 Err(InstructionError::AccountBorrowFailed),
1956 );
1957
1958 let (transaction_accounts, mut instruction_accounts) = get_accounts(
1960 &buffer_address,
1961 &upgrade_authority_address,
1962 &upgrade_authority_address,
1963 &elf_orig,
1964 &elf_new,
1965 );
1966 *instruction_accounts.get_mut(3).unwrap() = instruction_accounts.first().unwrap().clone();
1967 process_instruction(
1968 transaction_accounts,
1969 instruction_accounts,
1970 Err(InstructionError::AccountBorrowFailed),
1971 );
1972
1973 let (transaction_accounts, mut instruction_accounts) = get_accounts(
1975 &buffer_address,
1976 &upgrade_authority_address,
1977 &upgrade_authority_address,
1978 &elf_orig,
1979 &elf_new,
1980 );
1981 *instruction_accounts.get_mut(1).unwrap() = instruction_accounts.get(2).unwrap().clone();
1982 let instruction_data = bincode::serialize(&UpgradeableLoaderInstruction::Upgrade).unwrap();
1983
1984 process_instruction_with_setup(
1985 &bpf_loader_upgradeable::id(),
1986 &instruction_data,
1987 transaction_accounts.clone(),
1988 instruction_accounts.clone(),
1989 Err(InstructionError::InvalidAccountData),
1990 |invoke_context| {
1991 test_utils::load_all_invoked_programs(invoke_context);
1992 },
1993 );
1994 process_instruction(
1995 transaction_accounts.clone(),
1996 instruction_accounts.clone(),
1997 Err(InstructionError::InvalidAccountData),
1998 );
1999
2000 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2002 &buffer_address,
2003 &upgrade_authority_address,
2004 &upgrade_authority_address,
2005 &elf_orig,
2006 &elf_new,
2007 );
2008 transaction_accounts
2009 .get_mut(1)
2010 .unwrap()
2011 .1
2012 .set_owner(Pubkey::new_unique());
2013 process_instruction(
2014 transaction_accounts,
2015 instruction_accounts,
2016 Err(InstructionError::IncorrectProgramId),
2017 );
2018
2019 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2021 &buffer_address,
2022 &upgrade_authority_address,
2023 &upgrade_authority_address,
2024 &elf_orig,
2025 &elf_new,
2026 );
2027 instruction_accounts.get_mut(1).unwrap().is_writable = false;
2028 process_instruction(
2029 transaction_accounts,
2030 instruction_accounts,
2031 Err(InstructionError::InvalidArgument),
2032 );
2033
2034 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2036 &buffer_address,
2037 &upgrade_authority_address,
2038 &upgrade_authority_address,
2039 &elf_orig,
2040 &elf_new,
2041 );
2042 transaction_accounts
2043 .get_mut(1)
2044 .unwrap()
2045 .1
2046 .set_state(&UpgradeableLoaderState::Uninitialized)
2047 .unwrap();
2048 process_instruction(
2049 transaction_accounts,
2050 instruction_accounts,
2051 Err(InstructionError::InvalidAccountData),
2052 );
2053
2054 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2056 &buffer_address,
2057 &upgrade_authority_address,
2058 &upgrade_authority_address,
2059 &elf_orig,
2060 &elf_new,
2061 );
2062 let invalid_programdata_address = Pubkey::new_unique();
2063 transaction_accounts.get_mut(0).unwrap().0 = invalid_programdata_address;
2064 instruction_accounts.get_mut(0).unwrap().pubkey = invalid_programdata_address;
2065 process_instruction(
2066 transaction_accounts,
2067 instruction_accounts,
2068 Err(InstructionError::InvalidArgument),
2069 );
2070
2071 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2073 &buffer_address,
2074 &upgrade_authority_address,
2075 &upgrade_authority_address,
2076 &elf_orig,
2077 &elf_new,
2078 );
2079 transaction_accounts
2080 .get_mut(2)
2081 .unwrap()
2082 .1
2083 .set_state(&UpgradeableLoaderState::Uninitialized)
2084 .unwrap();
2085 process_instruction(
2086 transaction_accounts,
2087 instruction_accounts,
2088 Err(InstructionError::InvalidArgument),
2089 );
2090
2091 for buffer_balance in [0, 1_000_000, 15 * 1_000_000_000] {
2093 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2094 &buffer_address,
2095 &upgrade_authority_address,
2096 &upgrade_authority_address,
2097 &elf_orig,
2098 &elf_new,
2099 );
2100 transaction_accounts
2101 .get_mut(2)
2102 .unwrap()
2103 .1
2104 .set_lamports(buffer_balance);
2105 instruction_accounts.get_mut(2).unwrap().is_writable = false;
2106 process_instruction(
2107 transaction_accounts,
2108 instruction_accounts,
2109 Err(InstructionError::InvalidArgument),
2110 );
2111 }
2112
2113 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2119 &buffer_address,
2120 &upgrade_authority_address,
2121 &upgrade_authority_address,
2122 &elf_orig,
2123 &elf_new,
2124 );
2125 {
2126 let required_rent = |elf_len| {
2128 Rent::default()
2129 .minimum_balance(UpgradeableLoaderState::size_of_programdata(elf_len))
2130 };
2131 let rent_orig = required_rent(elf_orig.len());
2132 let rent_new = required_rent(elf_new.len());
2133 let programdata = &mut transaction_accounts.first_mut().unwrap().1;
2134 programdata.set_lamports(rent_orig);
2135 let buffer = &mut transaction_accounts.get_mut(2).unwrap().1;
2136 buffer.set_owner(Pubkey::new_unique());
2137 buffer.set_lamports(rent_new);
2138 }
2139 process_instruction(
2140 transaction_accounts,
2141 instruction_accounts,
2142 Err(InstructionError::IncorrectProgramId),
2143 );
2144
2145 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2150 &buffer_address,
2151 &upgrade_authority_address,
2152 &upgrade_authority_address,
2153 &elf_orig,
2154 &elf_new,
2155 );
2156 {
2157 let buffer = &mut transaction_accounts.get_mut(2).unwrap().1;
2159 buffer.set_owner(Pubkey::new_unique());
2160 buffer.set_lamports(0);
2161 }
2162 process_instruction(
2163 transaction_accounts,
2164 instruction_accounts,
2165 Err(InstructionError::IncorrectProgramId),
2166 );
2167
2168 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2174 &buffer_address,
2175 &upgrade_authority_address,
2176 &upgrade_authority_address,
2177 &elf_orig,
2178 &elf_new,
2179 );
2180 {
2181 let buffer = &mut transaction_accounts.get_mut(2).unwrap().1;
2183 buffer.set_owner(Pubkey::new_unique());
2184 buffer.set_lamports(0);
2185 truncate_data(buffer, UpgradeableLoaderState::size_of_buffer(0));
2186 }
2187 process_instruction(
2188 transaction_accounts,
2189 instruction_accounts,
2190 Err(InstructionError::IncorrectProgramId),
2191 );
2192
2193 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2195 &buffer_address,
2196 &upgrade_authority_address,
2197 &upgrade_authority_address,
2198 &elf_orig,
2199 &elf_new,
2200 );
2201 transaction_accounts.get_mut(2).unwrap().1 = AccountSharedData::new(
2202 1,
2203 UpgradeableLoaderState::size_of_buffer(
2204 elf_orig.len().max(elf_new.len()).saturating_add(1),
2205 ),
2206 &bpf_loader_upgradeable::id(),
2207 );
2208 transaction_accounts
2209 .get_mut(2)
2210 .unwrap()
2211 .1
2212 .set_state(&UpgradeableLoaderState::Buffer {
2213 authority_address: Some(upgrade_authority_address),
2214 })
2215 .unwrap();
2216 process_instruction(
2217 transaction_accounts,
2218 instruction_accounts,
2219 Err(InstructionError::AccountDataTooSmall),
2220 );
2221
2222 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2224 &buffer_address,
2225 &upgrade_authority_address,
2226 &upgrade_authority_address,
2227 &elf_orig,
2228 &elf_new,
2229 );
2230 transaction_accounts
2231 .get_mut(2)
2232 .unwrap()
2233 .1
2234 .set_state(&UpgradeableLoaderState::Buffer {
2235 authority_address: Some(upgrade_authority_address),
2236 })
2237 .unwrap();
2238 truncate_data(&mut transaction_accounts.get_mut(2).unwrap().1, 5);
2239 process_instruction(
2240 transaction_accounts,
2241 instruction_accounts,
2242 Err(InstructionError::InvalidAccountData),
2243 );
2244
2245 let (transaction_accounts, instruction_accounts) = get_accounts(
2247 &buffer_address,
2248 &buffer_address,
2249 &upgrade_authority_address,
2250 &elf_orig,
2251 &elf_new,
2252 );
2253 process_instruction(
2254 transaction_accounts,
2255 instruction_accounts,
2256 Err(InstructionError::IncorrectAuthority),
2257 );
2258
2259 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2261 &buffer_address,
2262 &buffer_address,
2263 &upgrade_authority_address,
2264 &elf_orig,
2265 &elf_new,
2266 );
2267 transaction_accounts
2268 .get_mut(2)
2269 .unwrap()
2270 .1
2271 .set_state(&UpgradeableLoaderState::Buffer {
2272 authority_address: None,
2273 })
2274 .unwrap();
2275 process_instruction(
2276 transaction_accounts,
2277 instruction_accounts,
2278 Err(InstructionError::IncorrectAuthority),
2279 );
2280
2281 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2283 &buffer_address,
2284 &buffer_address,
2285 &upgrade_authority_address,
2286 &elf_orig,
2287 &elf_new,
2288 );
2289 transaction_accounts
2290 .get_mut(0)
2291 .unwrap()
2292 .1
2293 .set_state(&UpgradeableLoaderState::ProgramData {
2294 slot: SLOT,
2295 upgrade_authority_address: None,
2296 })
2297 .unwrap();
2298 transaction_accounts
2299 .get_mut(2)
2300 .unwrap()
2301 .1
2302 .set_state(&UpgradeableLoaderState::Buffer {
2303 authority_address: None,
2304 })
2305 .unwrap();
2306 process_instruction(
2307 transaction_accounts,
2308 instruction_accounts,
2309 Err(InstructionError::IncorrectAuthority),
2310 );
2311
2312 let mut file =
2314 File::open("test_elfs/out/sbpfv0_verifier_err.so").expect("file open failed");
2315 let mut elf_new = Vec::new();
2316 file.read_to_end(&mut elf_new).unwrap();
2317 let (transaction_accounts, instruction_accounts) = get_accounts(
2318 &buffer_address,
2319 &upgrade_authority_address,
2320 &upgrade_authority_address,
2321 &elf_orig,
2322 &elf_new,
2323 );
2324 process_instruction(
2325 transaction_accounts,
2326 instruction_accounts,
2327 Err(InstructionError::InvalidAccountData),
2328 );
2329 }
2330
2331 #[test]
2332 fn test_bpf_loader_upgradeable_deploy_with_max_data_len() {
2333 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
2334 let mut elf = Vec::new();
2335 file.read_to_end(&mut elf).unwrap();
2336 const SLOT: u64 = 42;
2337 let payer_address = Pubkey::new_unique();
2338 let buffer_address = Pubkey::new_unique();
2339 let upgrade_authority_address = Pubkey::new_unique();
2340
2341 fn get_accounts(
2342 payer_address: &Pubkey,
2343 buffer_address: &Pubkey,
2344 buffer_authority: &Pubkey,
2345 upgrade_authority_address: &Pubkey,
2346 elf: &[u8],
2347 ) -> (Vec<(Pubkey, AccountSharedData)>, Vec<AccountMeta>) {
2348 let loader_id = bpf_loader_upgradeable::id();
2349 let program_address = Pubkey::new_unique();
2350 let rent = Rent::default();
2351 let min_program_balance =
2352 1.max(rent.minimum_balance(UpgradeableLoaderState::size_of_program()));
2353 let min_programdata_balance =
2354 1.max(rent.minimum_balance(UpgradeableLoaderState::size_of_programdata(elf.len())));
2355 let (programdata_address, _) =
2356 Pubkey::find_program_address(&[program_address.as_ref()], &loader_id);
2357 let mut buffer_account = AccountSharedData::new(
2358 1,
2359 UpgradeableLoaderState::size_of_buffer(elf.len()),
2360 &bpf_loader_upgradeable::id(),
2361 );
2362 buffer_account
2363 .set_state(&UpgradeableLoaderState::Buffer {
2364 authority_address: Some(*buffer_authority),
2365 })
2366 .unwrap();
2367 buffer_account
2368 .data_as_mut_slice()
2369 .get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
2370 .unwrap()
2371 .copy_from_slice(elf);
2372 let programdata_account = AccountSharedData::new(0, 0, &system_program::id());
2373 let mut program_account = AccountSharedData::new(
2374 min_program_balance,
2375 UpgradeableLoaderState::size_of_program(),
2376 &bpf_loader_upgradeable::id(),
2377 );
2378 program_account
2379 .set_state(&UpgradeableLoaderState::Uninitialized)
2380 .unwrap();
2381 let payer_account = AccountSharedData::new(
2382 min_programdata_balance.saturating_add(1),
2383 0,
2384 &system_program::id(),
2385 );
2386 let rent_account = create_account_for_test(&rent);
2387 let clock_account = create_account_for_test(&Clock {
2388 slot: SLOT,
2389 ..Clock::default()
2390 });
2391 let system_program_account = AccountSharedData::new(0, 0, &native_loader::id());
2392 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
2393 let transaction_accounts = vec![
2394 (*payer_address, payer_account),
2395 (programdata_address, programdata_account),
2396 (program_address, program_account),
2397 (*buffer_address, buffer_account),
2398 (sysvar::rent::id(), rent_account),
2399 (sysvar::clock::id(), clock_account),
2400 (system_program::id(), system_program_account),
2401 (*upgrade_authority_address, upgrade_authority_account),
2402 ];
2403 let instruction_accounts = vec![
2404 AccountMeta {
2405 pubkey: *payer_address,
2406 is_signer: true,
2407 is_writable: true,
2408 },
2409 AccountMeta {
2410 pubkey: programdata_address,
2411 is_signer: false,
2412 is_writable: true,
2413 },
2414 AccountMeta {
2415 pubkey: program_address,
2416 is_signer: false,
2417 is_writable: true,
2418 },
2419 AccountMeta {
2420 pubkey: *buffer_address,
2421 is_signer: false,
2422 is_writable: true,
2423 },
2424 AccountMeta {
2425 pubkey: sysvar::rent::id(),
2426 is_signer: false,
2427 is_writable: false,
2428 },
2429 AccountMeta {
2430 pubkey: sysvar::clock::id(),
2431 is_signer: false,
2432 is_writable: false,
2433 },
2434 AccountMeta {
2435 pubkey: system_program::id(),
2436 is_signer: false,
2437 is_writable: false,
2438 },
2439 AccountMeta {
2440 pubkey: *upgrade_authority_address,
2441 is_signer: true,
2442 is_writable: false,
2443 },
2444 ];
2445 (transaction_accounts, instruction_accounts)
2446 }
2447
2448 fn process_instruction(
2449 max_data_len: usize,
2450 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
2451 instruction_accounts: Vec<AccountMeta>,
2452 expected_result: Result<(), InstructionError>,
2453 ) -> Vec<AccountSharedData> {
2454 let instruction_data =
2455 bincode::serialize(&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
2456 max_data_len,
2457 })
2458 .unwrap();
2459 process_instruction_with_setup(
2460 &bpf_loader_upgradeable::id(),
2461 &instruction_data,
2462 transaction_accounts,
2463 instruction_accounts,
2464 expected_result,
2465 |invoke_context| {
2466 invoke_context.program_cache_for_tx_batch.replenish(
2468 system_program::id(),
2469 Arc::new(ProgramCacheEntry::new_builtin(
2470 0,
2471 solana_system_program::system_processor::Entrypoint::register,
2472 )),
2473 );
2474 },
2475 )
2476 }
2477
2478 let (transaction_accounts, instruction_accounts) = get_accounts(
2480 &payer_address,
2481 &buffer_address,
2482 &upgrade_authority_address,
2483 &upgrade_authority_address,
2484 &elf,
2485 );
2486 let programdata_address = instruction_accounts.get(1).unwrap().pubkey;
2487 let accounts = process_instruction(
2488 elf.len(),
2489 transaction_accounts,
2490 instruction_accounts,
2491 Ok(()),
2492 );
2493 let min_programdata_balance =
2494 Rent::default().minimum_balance(UpgradeableLoaderState::size_of_programdata(elf.len()));
2495 assert_eq!(min_programdata_balance, accounts.get(1).unwrap().lamports());
2496 assert_eq!(2, accounts.first().unwrap().lamports());
2497 assert_eq!(0, accounts.get(3).unwrap().lamports());
2498 assert_eq!(
2499 UpgradeableLoaderState::size_of_buffer(0),
2500 accounts.get(3).unwrap().data().len()
2501 );
2502 let state: UpgradeableLoaderState = accounts.get(1).unwrap().state().unwrap();
2503 assert_eq!(
2504 state,
2505 UpgradeableLoaderState::ProgramData {
2506 slot: SLOT,
2507 upgrade_authority_address: Some(upgrade_authority_address),
2508 }
2509 );
2510 for (i, byte) in accounts
2511 .get(1)
2512 .unwrap()
2513 .data()
2514 .get(
2515 UpgradeableLoaderState::size_of_programdata_metadata()
2516 ..UpgradeableLoaderState::size_of_programdata(elf.len()),
2517 )
2518 .unwrap()
2519 .iter()
2520 .enumerate()
2521 {
2522 assert_eq!(*elf.get(i).unwrap(), *byte);
2523 }
2524 let state: UpgradeableLoaderState = accounts.get(2).unwrap().state().unwrap();
2525 assert_eq!(
2526 state,
2527 UpgradeableLoaderState::Program {
2528 programdata_address,
2529 }
2530 );
2531 assert!(accounts.get(2).unwrap().executable());
2532
2533 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2535 &payer_address,
2536 &buffer_address,
2537 &upgrade_authority_address,
2538 &upgrade_authority_address,
2539 &elf,
2540 );
2541 let invalid_upgrade_authority_address = Pubkey::new_unique();
2542 transaction_accounts.get_mut(7).unwrap().0 = invalid_upgrade_authority_address;
2543 instruction_accounts.get_mut(7).unwrap().pubkey = invalid_upgrade_authority_address;
2544 process_instruction(
2545 elf.len(),
2546 transaction_accounts,
2547 instruction_accounts,
2548 Err(InstructionError::IncorrectAuthority),
2549 );
2550
2551 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2553 &payer_address,
2554 &buffer_address,
2555 &upgrade_authority_address,
2556 &upgrade_authority_address,
2557 &elf,
2558 );
2559 instruction_accounts.get_mut(7).unwrap().is_signer = false;
2560 process_instruction(
2561 elf.len(),
2562 transaction_accounts,
2563 instruction_accounts,
2564 Err(InstructionError::MissingRequiredSignature),
2565 );
2566
2567 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2569 &payer_address,
2570 &buffer_address,
2571 &upgrade_authority_address,
2572 &upgrade_authority_address,
2573 &elf,
2574 );
2575 *instruction_accounts.get_mut(0).unwrap() = instruction_accounts.get(3).unwrap().clone();
2576 process_instruction(
2577 elf.len(),
2578 transaction_accounts,
2579 instruction_accounts,
2580 Err(InstructionError::AccountBorrowFailed),
2581 );
2582
2583 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2592 &payer_address,
2593 &buffer_address,
2594 &upgrade_authority_address,
2595 &upgrade_authority_address,
2596 &elf,
2597 );
2598 transaction_accounts
2599 .get_mut(2)
2600 .unwrap()
2601 .1
2602 .set_owner(Pubkey::new_unique());
2603 process_instruction(
2604 elf.len(),
2605 transaction_accounts,
2606 instruction_accounts,
2607 Err(InstructionError::ExternalAccountDataModified),
2608 );
2609
2610 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2617 &payer_address,
2618 &buffer_address,
2619 &upgrade_authority_address,
2620 &upgrade_authority_address,
2621 &elf,
2622 );
2623 instruction_accounts.get_mut(2).unwrap().is_writable = false;
2624 process_instruction(
2625 elf.len(),
2626 transaction_accounts,
2627 instruction_accounts,
2628 Err(InstructionError::ReadonlyDataModified),
2629 );
2630
2631 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2633 &payer_address,
2634 &buffer_address,
2635 &upgrade_authority_address,
2636 &upgrade_authority_address,
2637 &elf,
2638 );
2639 transaction_accounts
2640 .get_mut(2)
2641 .unwrap()
2642 .1
2643 .set_state(&UpgradeableLoaderState::Program {
2644 programdata_address: Pubkey::new_unique(),
2645 })
2646 .unwrap();
2647 process_instruction(
2648 elf.len(),
2649 transaction_accounts,
2650 instruction_accounts,
2651 Err(InstructionError::AccountAlreadyInitialized),
2652 );
2653
2654 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2656 &payer_address,
2657 &buffer_address,
2658 &upgrade_authority_address,
2659 &upgrade_authority_address,
2660 &elf,
2661 );
2662 truncate_data(&mut transaction_accounts.get_mut(2).unwrap().1, 5);
2663 process_instruction(
2664 elf.len(),
2665 transaction_accounts,
2666 instruction_accounts,
2667 Err(InstructionError::AccountDataTooSmall),
2668 );
2669
2670 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2672 &payer_address,
2673 &buffer_address,
2674 &upgrade_authority_address,
2675 &upgrade_authority_address,
2676 &elf,
2677 );
2678 transaction_accounts.get_mut(2).unwrap().1.set_lamports(1);
2679 process_instruction(
2680 elf.len(),
2681 transaction_accounts,
2682 instruction_accounts,
2683 Err(InstructionError::ExecutableAccountNotRentExempt),
2684 );
2685
2686 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2688 &payer_address,
2689 &buffer_address,
2690 &upgrade_authority_address,
2691 &upgrade_authority_address,
2692 &elf,
2693 );
2694 let invalid_programdata_address = Pubkey::new_unique();
2695 transaction_accounts.get_mut(1).unwrap().0 = invalid_programdata_address;
2696 instruction_accounts.get_mut(1).unwrap().pubkey = invalid_programdata_address;
2697 process_instruction(
2698 elf.len(),
2699 transaction_accounts,
2700 instruction_accounts,
2701 Err(InstructionError::InvalidArgument),
2702 );
2703
2704 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2706 &payer_address,
2707 &buffer_address,
2708 &upgrade_authority_address,
2709 &upgrade_authority_address,
2710 &elf,
2711 );
2712 transaction_accounts
2713 .get_mut(3)
2714 .unwrap()
2715 .1
2716 .set_state(&UpgradeableLoaderState::Uninitialized)
2717 .unwrap();
2718 process_instruction(
2719 elf.len(),
2720 transaction_accounts,
2721 instruction_accounts,
2722 Err(InstructionError::InvalidArgument),
2723 );
2724
2725 for buffer_balance in [0, 1_000_000, 15 * 1_000_000_000] {
2727 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2728 &payer_address,
2729 &buffer_address,
2730 &upgrade_authority_address,
2731 &upgrade_authority_address,
2732 &elf,
2733 );
2734 transaction_accounts
2735 .get_mut(3)
2736 .unwrap()
2737 .1
2738 .set_lamports(buffer_balance);
2739 instruction_accounts.get_mut(3).unwrap().is_writable = false;
2740 process_instruction(
2741 elf.len(),
2742 transaction_accounts,
2743 instruction_accounts,
2744 Err(InstructionError::InvalidArgument),
2745 );
2746 }
2747
2748 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2754 &payer_address,
2755 &buffer_address,
2756 &upgrade_authority_address,
2757 &upgrade_authority_address,
2758 &elf,
2759 );
2760 {
2761 let required_rent = Rent::default()
2763 .minimum_balance(UpgradeableLoaderState::size_of_programdata(elf.len()));
2764 let programdata = &transaction_accounts.get(1).unwrap().1;
2765 assert!(programdata.lamports() < required_rent);
2766 let buffer = &mut transaction_accounts.get_mut(3).unwrap().1;
2767 buffer.set_owner(Pubkey::new_unique());
2768 buffer.set_lamports(required_rent);
2769 }
2770 process_instruction(
2771 elf.len(),
2772 transaction_accounts,
2773 instruction_accounts,
2774 Err(InstructionError::IncorrectProgramId),
2775 );
2776
2777 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2782 &payer_address,
2783 &buffer_address,
2784 &upgrade_authority_address,
2785 &upgrade_authority_address,
2786 &elf,
2787 );
2788 {
2789 let buffer = &mut transaction_accounts.get_mut(3).unwrap().1;
2791 buffer.set_owner(Pubkey::new_unique());
2792 buffer.set_lamports(0);
2793 }
2794 process_instruction(
2795 elf.len(),
2796 transaction_accounts,
2797 instruction_accounts,
2798 Err(InstructionError::IncorrectProgramId),
2799 );
2800
2801 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2807 &payer_address,
2808 &buffer_address,
2809 &upgrade_authority_address,
2810 &upgrade_authority_address,
2811 &elf,
2812 );
2813 {
2814 let buffer = &mut transaction_accounts.get_mut(3).unwrap().1;
2816 buffer.set_owner(Pubkey::new_unique());
2817 buffer.set_lamports(0);
2818 truncate_data(buffer, UpgradeableLoaderState::size_of_buffer(0));
2819 }
2820 process_instruction(
2821 elf.len(),
2822 transaction_accounts,
2823 instruction_accounts,
2824 Err(InstructionError::IncorrectProgramId),
2825 );
2826
2827 let (transaction_accounts, instruction_accounts) = get_accounts(
2829 &payer_address,
2830 &buffer_address,
2831 &upgrade_authority_address,
2832 &upgrade_authority_address,
2833 &elf,
2834 );
2835 process_instruction(
2836 elf.len().saturating_sub(1),
2837 transaction_accounts,
2838 instruction_accounts,
2839 Err(InstructionError::AccountDataTooSmall),
2840 );
2841
2842 let (transaction_accounts, instruction_accounts) = get_accounts(
2844 &payer_address,
2845 &buffer_address,
2846 &upgrade_authority_address,
2847 &upgrade_authority_address,
2848 &elf,
2849 );
2850 process_instruction(
2851 MAX_PERMITTED_DATA_LENGTH as usize,
2852 transaction_accounts,
2853 instruction_accounts,
2854 Err(InstructionError::InvalidArgument),
2855 );
2856
2857 let (transaction_accounts, instruction_accounts) = get_accounts(
2859 &payer_address,
2860 &buffer_address,
2861 &buffer_address,
2862 &upgrade_authority_address,
2863 &elf,
2864 );
2865 process_instruction(
2866 elf.len(),
2867 transaction_accounts,
2868 instruction_accounts,
2869 Err(InstructionError::IncorrectAuthority),
2870 );
2871
2872 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2874 &payer_address,
2875 &buffer_address,
2876 &buffer_address,
2877 &upgrade_authority_address,
2878 &elf,
2879 );
2880 transaction_accounts
2881 .get_mut(3)
2882 .unwrap()
2883 .1
2884 .set_state(&UpgradeableLoaderState::Buffer {
2885 authority_address: None,
2886 })
2887 .unwrap();
2888 process_instruction(
2889 elf.len(),
2890 transaction_accounts,
2891 instruction_accounts,
2892 Err(InstructionError::IncorrectAuthority),
2893 );
2894
2895 let mut file =
2897 File::open("test_elfs/out/sbpfv0_verifier_err.so").expect("file open failed");
2898 let mut elf = Vec::new();
2899 file.read_to_end(&mut elf).unwrap();
2900 let (transaction_accounts, instruction_accounts) = get_accounts(
2901 &payer_address,
2902 &buffer_address,
2903 &upgrade_authority_address,
2904 &upgrade_authority_address,
2905 &elf,
2906 );
2907 process_instruction(
2908 elf.len(),
2909 transaction_accounts,
2910 instruction_accounts,
2911 Err(InstructionError::InvalidAccountData),
2912 );
2913 }
2914
2915 #[test]
2916 fn test_bpf_loader_upgradeable_set_upgrade_authority() {
2917 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::SetAuthority).unwrap();
2918 let loader_id = bpf_loader_upgradeable::id();
2919 let slot = 0;
2920 let upgrade_authority_address = Pubkey::new_unique();
2921 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
2922 let new_upgrade_authority_address = Pubkey::new_unique();
2923 let new_upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
2924 let program_address = Pubkey::new_unique();
2925 let (programdata_address, _) = Pubkey::find_program_address(
2926 &[program_address.as_ref()],
2927 &bpf_loader_upgradeable::id(),
2928 );
2929 let mut programdata_account = AccountSharedData::new(
2930 1,
2931 UpgradeableLoaderState::size_of_programdata(0),
2932 &bpf_loader_upgradeable::id(),
2933 );
2934 programdata_account
2935 .set_state(&UpgradeableLoaderState::ProgramData {
2936 slot,
2937 upgrade_authority_address: Some(upgrade_authority_address),
2938 })
2939 .unwrap();
2940 let programdata_meta = AccountMeta {
2941 pubkey: programdata_address,
2942 is_signer: false,
2943 is_writable: true,
2944 };
2945 let upgrade_authority_meta = AccountMeta {
2946 pubkey: upgrade_authority_address,
2947 is_signer: true,
2948 is_writable: false,
2949 };
2950 let new_upgrade_authority_meta = AccountMeta {
2951 pubkey: new_upgrade_authority_address,
2952 is_signer: false,
2953 is_writable: false,
2954 };
2955
2956 let accounts = process_instruction(
2958 &loader_id,
2959 &instruction,
2960 vec![
2961 (programdata_address, programdata_account.clone()),
2962 (upgrade_authority_address, upgrade_authority_account.clone()),
2963 (
2964 new_upgrade_authority_address,
2965 new_upgrade_authority_account.clone(),
2966 ),
2967 ],
2968 vec![
2969 programdata_meta.clone(),
2970 upgrade_authority_meta.clone(),
2971 new_upgrade_authority_meta.clone(),
2972 ],
2973 Ok(()),
2974 );
2975 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
2976 assert_eq!(
2977 state,
2978 UpgradeableLoaderState::ProgramData {
2979 slot,
2980 upgrade_authority_address: Some(new_upgrade_authority_address),
2981 }
2982 );
2983
2984 let accounts = process_instruction(
2986 &loader_id,
2987 &instruction,
2988 vec![
2989 (programdata_address, programdata_account.clone()),
2990 (upgrade_authority_address, upgrade_authority_account.clone()),
2991 ],
2992 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
2993 Ok(()),
2994 );
2995 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
2996 assert_eq!(
2997 state,
2998 UpgradeableLoaderState::ProgramData {
2999 slot,
3000 upgrade_authority_address: None,
3001 }
3002 );
3003
3004 let mut file =
3006 File::open("test_elfs/out/sbpfv0_verifier_err.so").expect("file open failed");
3007 let mut elf = Vec::new();
3008 file.read_to_end(&mut elf).unwrap();
3009 programdata_account.resize(UpgradeableLoaderState::size_of_programdata(elf.len()), 0);
3010 programdata_account
3011 .data_as_mut_slice()
3012 .get_mut(UpgradeableLoaderState::size_of_programdata_metadata()..)
3013 .unwrap()
3014 .copy_from_slice(&elf);
3015 process_instruction(
3016 &loader_id,
3017 &instruction,
3018 vec![
3019 (programdata_address, programdata_account.clone()),
3020 (upgrade_authority_address, upgrade_authority_account.clone()),
3021 ],
3022 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3023 Err(InstructionError::InvalidAccountData),
3024 );
3025
3026 process_instruction(
3028 &loader_id,
3029 &instruction,
3030 vec![
3031 (programdata_address, programdata_account.clone()),
3032 (upgrade_authority_address, upgrade_authority_account.clone()),
3033 ],
3034 vec![
3035 programdata_meta.clone(),
3036 AccountMeta {
3037 pubkey: upgrade_authority_address,
3038 is_signer: false,
3039 is_writable: false,
3040 },
3041 ],
3042 Err(InstructionError::MissingRequiredSignature),
3043 );
3044
3045 let invalid_upgrade_authority_address = Pubkey::new_unique();
3047 process_instruction(
3048 &loader_id,
3049 &instruction,
3050 vec![
3051 (programdata_address, programdata_account.clone()),
3052 (
3053 invalid_upgrade_authority_address,
3054 upgrade_authority_account.clone(),
3055 ),
3056 (new_upgrade_authority_address, new_upgrade_authority_account),
3057 ],
3058 vec![
3059 programdata_meta.clone(),
3060 AccountMeta {
3061 pubkey: invalid_upgrade_authority_address,
3062 is_signer: true,
3063 is_writable: false,
3064 },
3065 new_upgrade_authority_meta,
3066 ],
3067 Err(InstructionError::IncorrectAuthority),
3068 );
3069
3070 programdata_account
3072 .set_state(&UpgradeableLoaderState::ProgramData {
3073 slot,
3074 upgrade_authority_address: None,
3075 })
3076 .unwrap();
3077 process_instruction(
3078 &loader_id,
3079 &instruction,
3080 vec![
3081 (programdata_address, programdata_account.clone()),
3082 (upgrade_authority_address, upgrade_authority_account.clone()),
3083 ],
3084 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3085 Err(InstructionError::Immutable),
3086 );
3087
3088 programdata_account
3090 .set_state(&UpgradeableLoaderState::Program {
3091 programdata_address: Pubkey::new_unique(),
3092 })
3093 .unwrap();
3094 process_instruction(
3095 &loader_id,
3096 &instruction,
3097 vec![
3098 (programdata_address, programdata_account.clone()),
3099 (upgrade_authority_address, upgrade_authority_account),
3100 ],
3101 vec![programdata_meta, upgrade_authority_meta],
3102 Err(InstructionError::InvalidArgument),
3103 );
3104 }
3105
3106 #[test]
3107 fn test_bpf_loader_upgradeable_set_upgrade_authority_checked() {
3108 let instruction =
3109 bincode::serialize(&UpgradeableLoaderInstruction::SetAuthorityChecked).unwrap();
3110 let loader_id = bpf_loader_upgradeable::id();
3111 let slot = 0;
3112 let upgrade_authority_address = Pubkey::new_unique();
3113 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3114 let new_upgrade_authority_address = Pubkey::new_unique();
3115 let new_upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3116 let program_address = Pubkey::new_unique();
3117 let (programdata_address, _) = Pubkey::find_program_address(
3118 &[program_address.as_ref()],
3119 &bpf_loader_upgradeable::id(),
3120 );
3121 let mut programdata_account = AccountSharedData::new(
3122 1,
3123 UpgradeableLoaderState::size_of_programdata(0),
3124 &bpf_loader_upgradeable::id(),
3125 );
3126 programdata_account
3127 .set_state(&UpgradeableLoaderState::ProgramData {
3128 slot,
3129 upgrade_authority_address: Some(upgrade_authority_address),
3130 })
3131 .unwrap();
3132 let programdata_meta = AccountMeta {
3133 pubkey: programdata_address,
3134 is_signer: false,
3135 is_writable: true,
3136 };
3137 let upgrade_authority_meta = AccountMeta {
3138 pubkey: upgrade_authority_address,
3139 is_signer: true,
3140 is_writable: false,
3141 };
3142 let new_upgrade_authority_meta = AccountMeta {
3143 pubkey: new_upgrade_authority_address,
3144 is_signer: true,
3145 is_writable: false,
3146 };
3147
3148 let accounts = process_instruction(
3150 &loader_id,
3151 &instruction,
3152 vec![
3153 (programdata_address, programdata_account.clone()),
3154 (upgrade_authority_address, upgrade_authority_account.clone()),
3155 (
3156 new_upgrade_authority_address,
3157 new_upgrade_authority_account.clone(),
3158 ),
3159 ],
3160 vec![
3161 programdata_meta.clone(),
3162 upgrade_authority_meta.clone(),
3163 new_upgrade_authority_meta.clone(),
3164 ],
3165 Ok(()),
3166 );
3167
3168 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3169 assert_eq!(
3170 state,
3171 UpgradeableLoaderState::ProgramData {
3172 slot,
3173 upgrade_authority_address: Some(new_upgrade_authority_address),
3174 }
3175 );
3176
3177 process_instruction(
3179 &loader_id,
3180 &instruction,
3181 vec![
3182 (programdata_address, programdata_account.clone()),
3183 (upgrade_authority_address, upgrade_authority_account.clone()),
3184 ],
3185 vec![
3186 programdata_meta.clone(),
3187 upgrade_authority_meta.clone(),
3188 upgrade_authority_meta.clone(),
3189 ],
3190 Ok(()),
3191 );
3192
3193 process_instruction(
3195 &loader_id,
3196 &instruction,
3197 vec![
3198 (programdata_address, programdata_account.clone()),
3199 (upgrade_authority_address, upgrade_authority_account.clone()),
3200 (
3201 new_upgrade_authority_address,
3202 new_upgrade_authority_account.clone(),
3203 ),
3204 ],
3205 vec![programdata_meta.clone(), new_upgrade_authority_meta.clone()],
3206 Err(InstructionError::MissingAccount),
3207 );
3208
3209 process_instruction(
3211 &loader_id,
3212 &instruction,
3213 vec![
3214 (programdata_address, programdata_account.clone()),
3215 (upgrade_authority_address, upgrade_authority_account.clone()),
3216 (
3217 new_upgrade_authority_address,
3218 new_upgrade_authority_account.clone(),
3219 ),
3220 ],
3221 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3222 Err(InstructionError::MissingAccount),
3223 );
3224
3225 process_instruction(
3227 &loader_id,
3228 &instruction,
3229 vec![
3230 (programdata_address, programdata_account.clone()),
3231 (upgrade_authority_address, upgrade_authority_account.clone()),
3232 (
3233 new_upgrade_authority_address,
3234 new_upgrade_authority_account.clone(),
3235 ),
3236 ],
3237 vec![
3238 programdata_meta.clone(),
3239 AccountMeta {
3240 pubkey: upgrade_authority_address,
3241 is_signer: false,
3242 is_writable: false,
3243 },
3244 new_upgrade_authority_meta.clone(),
3245 ],
3246 Err(InstructionError::MissingRequiredSignature),
3247 );
3248
3249 process_instruction(
3251 &loader_id,
3252 &instruction,
3253 vec![
3254 (programdata_address, programdata_account.clone()),
3255 (upgrade_authority_address, upgrade_authority_account.clone()),
3256 (
3257 new_upgrade_authority_address,
3258 new_upgrade_authority_account.clone(),
3259 ),
3260 ],
3261 vec![
3262 programdata_meta.clone(),
3263 upgrade_authority_meta.clone(),
3264 AccountMeta {
3265 pubkey: new_upgrade_authority_address,
3266 is_signer: false,
3267 is_writable: false,
3268 },
3269 ],
3270 Err(InstructionError::MissingRequiredSignature),
3271 );
3272
3273 let invalid_upgrade_authority_address = Pubkey::new_unique();
3275 process_instruction(
3276 &loader_id,
3277 &instruction,
3278 vec![
3279 (programdata_address, programdata_account.clone()),
3280 (
3281 invalid_upgrade_authority_address,
3282 upgrade_authority_account.clone(),
3283 ),
3284 (new_upgrade_authority_address, new_upgrade_authority_account),
3285 ],
3286 vec![
3287 programdata_meta.clone(),
3288 AccountMeta {
3289 pubkey: invalid_upgrade_authority_address,
3290 is_signer: true,
3291 is_writable: false,
3292 },
3293 new_upgrade_authority_meta.clone(),
3294 ],
3295 Err(InstructionError::IncorrectAuthority),
3296 );
3297
3298 programdata_account
3300 .set_state(&UpgradeableLoaderState::ProgramData {
3301 slot,
3302 upgrade_authority_address: None,
3303 })
3304 .unwrap();
3305 process_instruction(
3306 &loader_id,
3307 &instruction,
3308 vec![
3309 (programdata_address, programdata_account.clone()),
3310 (upgrade_authority_address, upgrade_authority_account.clone()),
3311 ],
3312 vec![
3313 programdata_meta.clone(),
3314 upgrade_authority_meta.clone(),
3315 new_upgrade_authority_meta.clone(),
3316 ],
3317 Err(InstructionError::Immutable),
3318 );
3319
3320 programdata_account
3322 .set_state(&UpgradeableLoaderState::Program {
3323 programdata_address: Pubkey::new_unique(),
3324 })
3325 .unwrap();
3326 process_instruction(
3327 &loader_id,
3328 &instruction,
3329 vec![
3330 (programdata_address, programdata_account.clone()),
3331 (upgrade_authority_address, upgrade_authority_account),
3332 ],
3333 vec![
3334 programdata_meta,
3335 upgrade_authority_meta,
3336 new_upgrade_authority_meta,
3337 ],
3338 Err(InstructionError::InvalidArgument),
3339 );
3340 }
3341
3342 #[test]
3343 fn test_bpf_loader_upgradeable_set_buffer_authority() {
3344 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::SetAuthority).unwrap();
3345 let loader_id = bpf_loader_upgradeable::id();
3346 let invalid_authority_address = Pubkey::new_unique();
3347 let authority_address = Pubkey::new_unique();
3348 let authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3349 let new_authority_address = Pubkey::new_unique();
3350 let new_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3351 let buffer_address = Pubkey::new_unique();
3352 let mut buffer_account =
3353 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(0), &loader_id);
3354 buffer_account
3355 .set_state(&UpgradeableLoaderState::Buffer {
3356 authority_address: Some(authority_address),
3357 })
3358 .unwrap();
3359 let mut transaction_accounts = vec![
3360 (buffer_address, buffer_account.clone()),
3361 (authority_address, authority_account.clone()),
3362 (new_authority_address, new_authority_account.clone()),
3363 ];
3364 let buffer_meta = AccountMeta {
3365 pubkey: buffer_address,
3366 is_signer: false,
3367 is_writable: true,
3368 };
3369 let authority_meta = AccountMeta {
3370 pubkey: authority_address,
3371 is_signer: true,
3372 is_writable: false,
3373 };
3374 let new_authority_meta = AccountMeta {
3375 pubkey: new_authority_address,
3376 is_signer: false,
3377 is_writable: false,
3378 };
3379
3380 let accounts = process_instruction(
3382 &loader_id,
3383 &instruction,
3384 transaction_accounts.clone(),
3385 vec![buffer_meta.clone(), authority_meta.clone()],
3386 Err(InstructionError::IncorrectAuthority),
3387 );
3388 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3389 assert_eq!(
3390 state,
3391 UpgradeableLoaderState::Buffer {
3392 authority_address: Some(authority_address),
3393 }
3394 );
3395
3396 buffer_account
3398 .set_state(&UpgradeableLoaderState::Buffer {
3399 authority_address: Some(authority_address),
3400 })
3401 .unwrap();
3402 let accounts = process_instruction(
3403 &loader_id,
3404 &instruction,
3405 transaction_accounts.clone(),
3406 vec![
3407 buffer_meta.clone(),
3408 authority_meta.clone(),
3409 new_authority_meta.clone(),
3410 ],
3411 Ok(()),
3412 );
3413 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3414 assert_eq!(
3415 state,
3416 UpgradeableLoaderState::Buffer {
3417 authority_address: Some(new_authority_address),
3418 }
3419 );
3420
3421 process_instruction(
3423 &loader_id,
3424 &instruction,
3425 transaction_accounts.clone(),
3426 vec![
3427 buffer_meta.clone(),
3428 AccountMeta {
3429 pubkey: authority_address,
3430 is_signer: false,
3431 is_writable: false,
3432 },
3433 new_authority_meta.clone(),
3434 ],
3435 Err(InstructionError::MissingRequiredSignature),
3436 );
3437
3438 process_instruction(
3440 &loader_id,
3441 &instruction,
3442 vec![
3443 (buffer_address, buffer_account.clone()),
3444 (invalid_authority_address, authority_account),
3445 (new_authority_address, new_authority_account),
3446 ],
3447 vec![
3448 buffer_meta.clone(),
3449 AccountMeta {
3450 pubkey: invalid_authority_address,
3451 is_signer: true,
3452 is_writable: false,
3453 },
3454 new_authority_meta.clone(),
3455 ],
3456 Err(InstructionError::IncorrectAuthority),
3457 );
3458
3459 process_instruction(
3461 &loader_id,
3462 &instruction,
3463 transaction_accounts.clone(),
3464 vec![buffer_meta.clone(), authority_meta.clone()],
3465 Err(InstructionError::IncorrectAuthority),
3466 );
3467
3468 transaction_accounts
3470 .get_mut(0)
3471 .unwrap()
3472 .1
3473 .set_state(&UpgradeableLoaderState::Buffer {
3474 authority_address: None,
3475 })
3476 .unwrap();
3477 process_instruction(
3478 &loader_id,
3479 &instruction,
3480 transaction_accounts.clone(),
3481 vec![
3482 buffer_meta.clone(),
3483 authority_meta.clone(),
3484 new_authority_meta.clone(),
3485 ],
3486 Err(InstructionError::Immutable),
3487 );
3488
3489 transaction_accounts
3491 .get_mut(0)
3492 .unwrap()
3493 .1
3494 .set_state(&UpgradeableLoaderState::Program {
3495 programdata_address: Pubkey::new_unique(),
3496 })
3497 .unwrap();
3498 process_instruction(
3499 &loader_id,
3500 &instruction,
3501 transaction_accounts.clone(),
3502 vec![buffer_meta, authority_meta, new_authority_meta],
3503 Err(InstructionError::InvalidArgument),
3504 );
3505 }
3506
3507 #[test]
3508 fn test_bpf_loader_upgradeable_set_buffer_authority_checked() {
3509 let instruction =
3510 bincode::serialize(&UpgradeableLoaderInstruction::SetAuthorityChecked).unwrap();
3511 let loader_id = bpf_loader_upgradeable::id();
3512 let invalid_authority_address = Pubkey::new_unique();
3513 let authority_address = Pubkey::new_unique();
3514 let authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3515 let new_authority_address = Pubkey::new_unique();
3516 let new_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3517 let buffer_address = Pubkey::new_unique();
3518 let mut buffer_account =
3519 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(0), &loader_id);
3520 buffer_account
3521 .set_state(&UpgradeableLoaderState::Buffer {
3522 authority_address: Some(authority_address),
3523 })
3524 .unwrap();
3525 let mut transaction_accounts = vec![
3526 (buffer_address, buffer_account.clone()),
3527 (authority_address, authority_account.clone()),
3528 (new_authority_address, new_authority_account.clone()),
3529 ];
3530 let buffer_meta = AccountMeta {
3531 pubkey: buffer_address,
3532 is_signer: false,
3533 is_writable: true,
3534 };
3535 let authority_meta = AccountMeta {
3536 pubkey: authority_address,
3537 is_signer: true,
3538 is_writable: false,
3539 };
3540 let new_authority_meta = AccountMeta {
3541 pubkey: new_authority_address,
3542 is_signer: true,
3543 is_writable: false,
3544 };
3545
3546 buffer_account
3548 .set_state(&UpgradeableLoaderState::Buffer {
3549 authority_address: Some(authority_address),
3550 })
3551 .unwrap();
3552 let accounts = process_instruction(
3553 &loader_id,
3554 &instruction,
3555 transaction_accounts.clone(),
3556 vec![
3557 buffer_meta.clone(),
3558 authority_meta.clone(),
3559 new_authority_meta.clone(),
3560 ],
3561 Ok(()),
3562 );
3563 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3564 assert_eq!(
3565 state,
3566 UpgradeableLoaderState::Buffer {
3567 authority_address: Some(new_authority_address),
3568 }
3569 );
3570
3571 process_instruction(
3573 &loader_id,
3574 &instruction,
3575 transaction_accounts.clone(),
3576 vec![
3577 buffer_meta.clone(),
3578 authority_meta.clone(),
3579 authority_meta.clone(),
3580 ],
3581 Ok(()),
3582 );
3583
3584 process_instruction(
3586 &loader_id,
3587 &instruction,
3588 transaction_accounts.clone(),
3589 vec![buffer_meta.clone(), new_authority_meta.clone()],
3590 Err(InstructionError::MissingAccount),
3591 );
3592
3593 process_instruction(
3595 &loader_id,
3596 &instruction,
3597 transaction_accounts.clone(),
3598 vec![buffer_meta.clone(), authority_meta.clone()],
3599 Err(InstructionError::MissingAccount),
3600 );
3601
3602 process_instruction(
3604 &loader_id,
3605 &instruction,
3606 vec![
3607 (buffer_address, buffer_account.clone()),
3608 (invalid_authority_address, authority_account),
3609 (new_authority_address, new_authority_account),
3610 ],
3611 vec![
3612 buffer_meta.clone(),
3613 AccountMeta {
3614 pubkey: invalid_authority_address,
3615 is_signer: true,
3616 is_writable: false,
3617 },
3618 new_authority_meta.clone(),
3619 ],
3620 Err(InstructionError::IncorrectAuthority),
3621 );
3622
3623 process_instruction(
3625 &loader_id,
3626 &instruction,
3627 transaction_accounts.clone(),
3628 vec![
3629 buffer_meta.clone(),
3630 AccountMeta {
3631 pubkey: authority_address,
3632 is_signer: false,
3633 is_writable: false,
3634 },
3635 new_authority_meta.clone(),
3636 ],
3637 Err(InstructionError::MissingRequiredSignature),
3638 );
3639
3640 process_instruction(
3642 &loader_id,
3643 &instruction,
3644 transaction_accounts.clone(),
3645 vec![
3646 buffer_meta.clone(),
3647 authority_meta.clone(),
3648 AccountMeta {
3649 pubkey: new_authority_address,
3650 is_signer: false,
3651 is_writable: false,
3652 },
3653 ],
3654 Err(InstructionError::MissingRequiredSignature),
3655 );
3656
3657 transaction_accounts
3659 .get_mut(0)
3660 .unwrap()
3661 .1
3662 .set_state(&UpgradeableLoaderState::Program {
3663 programdata_address: Pubkey::new_unique(),
3664 })
3665 .unwrap();
3666 process_instruction(
3667 &loader_id,
3668 &instruction,
3669 transaction_accounts.clone(),
3670 vec![
3671 buffer_meta.clone(),
3672 authority_meta.clone(),
3673 new_authority_meta.clone(),
3674 ],
3675 Err(InstructionError::InvalidArgument),
3676 );
3677
3678 transaction_accounts
3680 .get_mut(0)
3681 .unwrap()
3682 .1
3683 .set_state(&UpgradeableLoaderState::Buffer {
3684 authority_address: None,
3685 })
3686 .unwrap();
3687 process_instruction(
3688 &loader_id,
3689 &instruction,
3690 transaction_accounts.clone(),
3691 vec![buffer_meta, authority_meta, new_authority_meta],
3692 Err(InstructionError::Immutable),
3693 );
3694 }
3695
3696 #[test]
3697 fn test_bpf_loader_upgradeable_close() {
3698 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Close).unwrap();
3699 let loader_id = bpf_loader_upgradeable::id();
3700 let invalid_authority_address = Pubkey::new_unique();
3701 let authority_address = Pubkey::new_unique();
3702 let authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3703 let recipient_address = Pubkey::new_unique();
3704 let recipient_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3705 let buffer_address = Pubkey::new_unique();
3706 let mut buffer_account =
3707 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(128), &loader_id);
3708 buffer_account
3709 .set_state(&UpgradeableLoaderState::Buffer {
3710 authority_address: Some(authority_address),
3711 })
3712 .unwrap();
3713 let uninitialized_address = Pubkey::new_unique();
3714 let mut uninitialized_account = AccountSharedData::new(
3715 1,
3716 UpgradeableLoaderState::size_of_programdata(0),
3717 &loader_id,
3718 );
3719 uninitialized_account
3720 .set_state(&UpgradeableLoaderState::Uninitialized)
3721 .unwrap();
3722 let programdata_address = Pubkey::new_unique();
3723 let mut programdata_account = AccountSharedData::new(
3724 1,
3725 UpgradeableLoaderState::size_of_programdata(128),
3726 &loader_id,
3727 );
3728 programdata_account
3729 .set_state(&UpgradeableLoaderState::ProgramData {
3730 slot: 0,
3731 upgrade_authority_address: Some(authority_address),
3732 })
3733 .unwrap();
3734 let program_address = Pubkey::new_unique();
3735 let mut program_account =
3736 AccountSharedData::new(1, UpgradeableLoaderState::size_of_program(), &loader_id);
3737 program_account.set_executable(true);
3738 program_account
3739 .set_state(&UpgradeableLoaderState::Program {
3740 programdata_address,
3741 })
3742 .unwrap();
3743 let clock_account = create_account_for_test(&Clock {
3744 slot: 1,
3745 ..Clock::default()
3746 });
3747 let transaction_accounts = vec![
3748 (buffer_address, buffer_account.clone()),
3749 (recipient_address, recipient_account.clone()),
3750 (authority_address, authority_account.clone()),
3751 ];
3752 let buffer_meta = AccountMeta {
3753 pubkey: buffer_address,
3754 is_signer: false,
3755 is_writable: true,
3756 };
3757 let recipient_meta = AccountMeta {
3758 pubkey: recipient_address,
3759 is_signer: false,
3760 is_writable: true,
3761 };
3762 let authority_meta = AccountMeta {
3763 pubkey: authority_address,
3764 is_signer: true,
3765 is_writable: false,
3766 };
3767
3768 let accounts = process_instruction(
3770 &loader_id,
3771 &instruction,
3772 transaction_accounts,
3773 vec![
3774 buffer_meta.clone(),
3775 recipient_meta.clone(),
3776 authority_meta.clone(),
3777 ],
3778 Ok(()),
3779 );
3780 assert_eq!(0, accounts.first().unwrap().lamports());
3781 assert_eq!(2, accounts.get(1).unwrap().lamports());
3782 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3783 assert_eq!(state, UpgradeableLoaderState::Uninitialized);
3784 assert_eq!(
3785 UpgradeableLoaderState::size_of_uninitialized(),
3786 accounts.first().unwrap().data().len()
3787 );
3788
3789 process_instruction(
3791 &loader_id,
3792 &instruction,
3793 vec![
3794 (buffer_address, buffer_account.clone()),
3795 (recipient_address, recipient_account.clone()),
3796 (invalid_authority_address, authority_account.clone()),
3797 ],
3798 vec![
3799 buffer_meta,
3800 recipient_meta.clone(),
3801 AccountMeta {
3802 pubkey: invalid_authority_address,
3803 is_signer: true,
3804 is_writable: false,
3805 },
3806 ],
3807 Err(InstructionError::IncorrectAuthority),
3808 );
3809
3810 let accounts = process_instruction(
3812 &loader_id,
3813 &instruction,
3814 vec![
3815 (uninitialized_address, uninitialized_account.clone()),
3816 (recipient_address, recipient_account.clone()),
3817 (invalid_authority_address, authority_account.clone()),
3818 ],
3819 vec![
3820 AccountMeta {
3821 pubkey: uninitialized_address,
3822 is_signer: false,
3823 is_writable: true,
3824 },
3825 recipient_meta.clone(),
3826 authority_meta.clone(),
3827 ],
3828 Ok(()),
3829 );
3830 assert_eq!(0, accounts.first().unwrap().lamports());
3831 assert_eq!(2, accounts.get(1).unwrap().lamports());
3832 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3833 assert_eq!(state, UpgradeableLoaderState::Uninitialized);
3834 assert_eq!(
3835 UpgradeableLoaderState::size_of_uninitialized(),
3836 accounts.first().unwrap().data().len()
3837 );
3838
3839 process_instruction(
3841 &loader_id,
3842 &instruction,
3843 vec![
3844 (programdata_address, programdata_account.clone()),
3845 (recipient_address, recipient_account.clone()),
3846 (authority_address, authority_account.clone()),
3847 (program_address, program_account.clone()),
3848 (sysvar::clock::id(), clock_account.clone()),
3849 ],
3850 vec![
3851 AccountMeta {
3852 pubkey: programdata_address,
3853 is_signer: false,
3854 is_writable: true,
3855 },
3856 recipient_meta.clone(),
3857 authority_meta.clone(),
3858 AccountMeta {
3859 pubkey: program_address,
3860 is_signer: false,
3861 is_writable: false,
3862 },
3863 ],
3864 Err(InstructionError::InvalidArgument),
3865 );
3866
3867 let accounts = process_instruction(
3869 &loader_id,
3870 &instruction,
3871 vec![
3872 (programdata_address, programdata_account.clone()),
3873 (recipient_address, recipient_account.clone()),
3874 (authority_address, authority_account.clone()),
3875 (program_address, program_account.clone()),
3876 (sysvar::clock::id(), clock_account.clone()),
3877 ],
3878 vec![
3879 AccountMeta {
3880 pubkey: programdata_address,
3881 is_signer: false,
3882 is_writable: true,
3883 },
3884 recipient_meta,
3885 authority_meta,
3886 AccountMeta {
3887 pubkey: program_address,
3888 is_signer: false,
3889 is_writable: true,
3890 },
3891 ],
3892 Ok(()),
3893 );
3894 assert_eq!(0, accounts.first().unwrap().lamports());
3895 assert_eq!(2, accounts.get(1).unwrap().lamports());
3896 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3897 assert_eq!(state, UpgradeableLoaderState::Uninitialized);
3898 assert_eq!(
3899 UpgradeableLoaderState::size_of_uninitialized(),
3900 accounts.first().unwrap().data().len()
3901 );
3902
3903 programdata_account = accounts.first().unwrap().clone();
3905 program_account = accounts.get(3).unwrap().clone();
3906 process_instruction(
3907 &program_address,
3908 &[],
3909 vec![
3910 (programdata_address, programdata_account.clone()),
3911 (program_address, program_account.clone()),
3912 ],
3913 Vec::new(),
3914 Err(InstructionError::UnsupportedProgramId),
3915 );
3916
3917 process_instruction(
3919 &loader_id,
3920 &bincode::serialize(&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
3921 max_data_len: 0,
3922 })
3923 .unwrap(),
3924 vec![
3925 (recipient_address, recipient_account),
3926 (programdata_address, programdata_account),
3927 (program_address, program_account),
3928 (buffer_address, buffer_account),
3929 (
3930 sysvar::rent::id(),
3931 create_account_for_test(&Rent::default()),
3932 ),
3933 (sysvar::clock::id(), clock_account),
3934 (
3935 system_program::id(),
3936 AccountSharedData::new(0, 0, &system_program::id()),
3937 ),
3938 (authority_address, authority_account),
3939 ],
3940 vec![
3941 AccountMeta {
3942 pubkey: recipient_address,
3943 is_signer: true,
3944 is_writable: true,
3945 },
3946 AccountMeta {
3947 pubkey: programdata_address,
3948 is_signer: false,
3949 is_writable: true,
3950 },
3951 AccountMeta {
3952 pubkey: program_address,
3953 is_signer: false,
3954 is_writable: true,
3955 },
3956 AccountMeta {
3957 pubkey: buffer_address,
3958 is_signer: false,
3959 is_writable: false,
3960 },
3961 AccountMeta {
3962 pubkey: sysvar::rent::id(),
3963 is_signer: false,
3964 is_writable: false,
3965 },
3966 AccountMeta {
3967 pubkey: sysvar::clock::id(),
3968 is_signer: false,
3969 is_writable: false,
3970 },
3971 AccountMeta {
3972 pubkey: system_program::id(),
3973 is_signer: false,
3974 is_writable: false,
3975 },
3976 AccountMeta {
3977 pubkey: authority_address,
3978 is_signer: false,
3979 is_writable: false,
3980 },
3981 ],
3982 Err(InstructionError::AccountAlreadyInitialized),
3983 );
3984 }
3985
3986 fn fuzz<F>(
3988 bytes: &[u8],
3989 outer_iters: usize,
3990 inner_iters: usize,
3991 offset: Range<usize>,
3992 value: Range<u8>,
3993 work: F,
3994 ) where
3995 F: Fn(&mut [u8]),
3996 {
3997 let mut rng = rand::rng();
3998 for _ in 0..outer_iters {
3999 let mut mangled_bytes = bytes.to_vec();
4000 for _ in 0..inner_iters {
4001 let offset = rng.random_range(offset.start..offset.end);
4002 let value = rng.random_range(value.start..value.end);
4003 *mangled_bytes.get_mut(offset).unwrap() = value;
4004 work(&mut mangled_bytes);
4005 }
4006 }
4007 }
4008
4009 #[test]
4010 #[ignore]
4011 fn test_fuzz() {
4012 let loader_id = bpf_loader::id();
4013 let program_id = Pubkey::new_unique();
4014
4015 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
4017 let mut elf = Vec::new();
4018 file.read_to_end(&mut elf).unwrap();
4019
4020 fuzz(
4022 &elf,
4023 1_000_000_000,
4024 100,
4025 0..elf.len(),
4026 0..255,
4027 |bytes: &mut [u8]| {
4028 let mut program_account = AccountSharedData::new(1, 0, &loader_id);
4029 program_account.set_data(bytes.to_vec());
4030 program_account.set_executable(true);
4031 process_instruction(
4032 &program_id,
4033 &[],
4034 vec![(program_id, program_account)],
4035 Vec::new(),
4036 Ok(()),
4037 );
4038 },
4039 );
4040 }
4041
4042 #[test]
4043 fn test_calculate_heap_cost() {
4044 let heap_cost = 8_u64;
4045
4046 assert_eq!(0, calculate_heap_cost(31 * 1024, heap_cost));
4050
4051 assert_eq!(0, calculate_heap_cost(32 * 1024, heap_cost));
4053
4054 assert_eq!(heap_cost, calculate_heap_cost(33 * 1024, heap_cost));
4056
4057 assert_eq!(heap_cost, calculate_heap_cost(64 * 1024, heap_cost));
4059 }
4060
4061 fn deploy_test_program(
4062 invoke_context: &mut InvokeContext,
4063 program_id: Pubkey,
4064 ) -> Result<(), InstructionError> {
4065 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
4066 let mut elf = Vec::new();
4067 file.read_to_end(&mut elf).unwrap();
4068 deploy_program!(
4069 invoke_context,
4070 &program_id,
4071 &bpf_loader_upgradeable::id(),
4072 &elf,
4073 2_u64,
4074 true, );
4076 Ok(())
4077 }
4078
4079 #[cfg(feature = "shuttle-test")]
4098 const PROGRAM_USAGE_COUNT_RANDOM_ITERATIONS: usize = 100;
4099
4100 #[test]
4101 fn test_program_usage_count_on_upgrade() {
4102 #[cfg(feature = "shuttle-test")]
4103 shuttle::check_random(
4104 do_test_program_usage_count_on_upgrade,
4105 PROGRAM_USAGE_COUNT_RANDOM_ITERATIONS,
4106 );
4107 #[cfg(not(feature = "shuttle-test"))]
4108 do_test_program_usage_count_on_upgrade();
4109 }
4110
4111 fn do_test_program_usage_count_on_upgrade() {
4112 let transaction_accounts = vec![(
4113 sysvar::epoch_schedule::id(),
4114 create_account_for_test(&EpochSchedule::default()),
4115 )];
4116 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4117 let program_id = Pubkey::new_unique();
4118 let env = ProgramRuntimeEnvironment::from(BuiltinProgram::new_mock());
4119 let stats = ProgramStatistics {
4120 uses: 100.into(),
4121 ..Default::default()
4122 };
4123 let program = ProgramCacheEntry {
4124 program: ProgramCacheEntryType::Unloaded(env),
4125 account_owner: ProgramCacheEntryOwner::LoaderV2,
4126 deployment_slot: 0,
4127 stats: stats.into(),
4128 latest_access_slot: AtomicU64::new(0),
4129 };
4130 invoke_context
4131 .program_cache_for_tx_batch
4132 .replenish(program_id, Arc::new(program));
4133 invoke_context
4134 .program_cache_for_tx_batch
4135 .set_slot_for_tests(2);
4136
4137 assert_matches!(
4138 deploy_test_program(&mut invoke_context, program_id,),
4139 Ok(())
4140 );
4141
4142 let updated_program = invoke_context
4143 .program_cache_for_tx_batch
4144 .find(&program_id)
4145 .expect("Didn't find upgraded program in the cache");
4146
4147 assert_eq!(updated_program.deployment_slot, 2);
4148 assert_eq!(updated_program.stats.uses.load(Ordering::Relaxed), 100);
4149 }
4150
4151 #[test]
4152 fn test_program_usage_count_on_non_upgrade() {
4153 #[cfg(feature = "shuttle-test")]
4154 shuttle::check_random(
4155 do_test_program_usage_count_on_non_upgrade,
4156 PROGRAM_USAGE_COUNT_RANDOM_ITERATIONS,
4157 );
4158 #[cfg(not(feature = "shuttle-test"))]
4159 do_test_program_usage_count_on_non_upgrade();
4160 }
4161
4162 fn do_test_program_usage_count_on_non_upgrade() {
4163 let transaction_accounts = vec![(
4164 sysvar::epoch_schedule::id(),
4165 create_account_for_test(&EpochSchedule::default()),
4166 )];
4167 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4168 let program_id = Pubkey::new_unique();
4169 let env = ProgramRuntimeEnvironment::from(BuiltinProgram::new_mock());
4170 let stats = ProgramStatistics {
4171 uses: 100.into(),
4172 ..Default::default()
4173 };
4174 let program = ProgramCacheEntry {
4175 program: ProgramCacheEntryType::Unloaded(env),
4176 account_owner: ProgramCacheEntryOwner::LoaderV2,
4177 deployment_slot: 0,
4178 stats: stats.into(),
4179 latest_access_slot: AtomicU64::new(0),
4180 };
4181 invoke_context
4182 .program_cache_for_tx_batch
4183 .replenish(program_id, Arc::new(program));
4184 invoke_context
4185 .program_cache_for_tx_batch
4186 .set_slot_for_tests(2);
4187
4188 let program_id2 = Pubkey::new_unique();
4189 assert_matches!(
4190 deploy_test_program(&mut invoke_context, program_id2),
4191 Ok(())
4192 );
4193
4194 let program2 = invoke_context
4195 .program_cache_for_tx_batch
4196 .find(&program_id2)
4197 .expect("Didn't find upgraded program in the cache");
4198
4199 assert_eq!(program2.deployment_slot, 2);
4200 assert_eq!(program2.stats.uses.load(Ordering::Relaxed), 0);
4201 }
4202}