Verify BPF ELF during finalize (#7266)
This commit is contained in:
		| @@ -34,6 +34,13 @@ pub fn create_vm(prog: &[u8]) -> Result<(EbpfVm, MemoryRegion), Error> { | ||||
|     Ok((vm, heap_region)) | ||||
| } | ||||
|  | ||||
| pub fn check_elf(prog: &[u8]) -> Result<(), Error> { | ||||
|     let mut vm = EbpfVm::new(None)?; | ||||
|     vm.set_verifier(bpf_verifier::check)?; | ||||
|     vm.set_elf(&prog)?; | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| fn serialize_parameters( | ||||
|     program_id: &Pubkey, | ||||
|     keyed_accounts: &mut [KeyedAccount], | ||||
| @@ -118,6 +125,11 @@ pub fn process_instruction( | ||||
|                     return Err(InstructionError::MissingRequiredSignature); | ||||
|                 } | ||||
|  | ||||
|                 if let Err(e) = check_elf(&program.account.data) { | ||||
|                     warn!("Invalid ELF: {}", e); | ||||
|                     return Err(InstructionError::InvalidAccountData); | ||||
|                 } | ||||
|  | ||||
|                 rent::verify_rent_exemption(&program, &rent)?; | ||||
|  | ||||
|                 program.account.executable = true; | ||||
| @@ -244,7 +256,11 @@ mod tests { | ||||
|         let program_id = Pubkey::new_rand(); | ||||
|         let program_key = Pubkey::new_rand(); | ||||
|         let rent_key = rent::id(); | ||||
|         let mut file = File::open("test_elfs/noop.so").expect("file open failed"); | ||||
|         let mut elf = Vec::new(); | ||||
|         file.read_to_end(&mut elf).unwrap(); | ||||
|         let mut program_account = Account::new(1, 0, &program_id); | ||||
|         program_account.data = elf; | ||||
|         let mut keyed_accounts = vec![KeyedAccount::new(&program_key, false, &mut program_account)]; | ||||
|         let ix_data = bincode::serialize(&LoaderInstruction::Finalize).unwrap(); | ||||
|  | ||||
| @@ -273,6 +289,17 @@ mod tests { | ||||
|             process_instruction(&program_id, &mut keyed_accounts, &ix_data) | ||||
|         ); | ||||
|         assert!(keyed_accounts[0].account.executable); | ||||
|  | ||||
|         // Case: Finalize | ||||
|         program_account.data[0] = 0; // bad elf | ||||
|         let mut keyed_accounts = vec![ | ||||
|             KeyedAccount::new(&program_key, true, &mut program_account), | ||||
|             KeyedAccount::new(&rent_key, false, &mut rent_account), | ||||
|         ]; | ||||
|         assert_eq!( | ||||
|             Err(InstructionError::InvalidAccountData), | ||||
|             process_instruction(&program_id, &mut keyed_accounts, &ix_data) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user